- name: Download DCMTK Support libraries
shell: pwsh
run: |
- C:\msys64\usr\bin\wget.exe -O dcmtk_support.zip https://dicom.offis.de/download/dcmtk/dcmtk368/support/dcmtk-3.6.8-win64-support-MD-msvc-17.4.zip
+ C:\msys64\usr\bin\wget.exe -O dcmtk_support.zip https://dicom.offis.de/download/dcmtk/dcmtk370/support/dcmtk-3.7.0-win64-support-MD-msvc-17.8.zip
# Uncompress support libraries into directory c:\dcmtk_support\libs.
# We rename the original directory to libs so that the rest of the script
- # can use the ame path even if the support library package is updated
+ # can use the same path even if the support library package is updated
# in the future in the download task above.
- name: Uncompress Support libraries
shell: pwsh
echo "Step 2"
cd ${{ github.workspace }}\dcmtk-build
echo "Step 3"
- cmake -G "Visual Studio 17 2022" -Ax64 -DDCMTK_MODULES:STR="ofstd;oflog;oficonv;dcmdata;dcmimgle;dcmimage;dcmjpeg;dcmjpls;dcmtls;dcmnet;dcmsr;dcmsign;dcmwlm;dcmqrdb;dcmpstat;dcmrt;dcmiod;dcmfg;dcmseg;dcmtract;dcmpmap;dcmect" -DDCMTK_ENABLE_BUILTIN_OFICONV_DATA:BOOL=On -DBUILD_SHARED_LIBS:BOOL=ON -DDCMTK_SUPPORT_LIBRARIES_DIR:PATH=c:\dcmtk_support\libs -DCMAKE_INSTALL_PREFIX:PATH=${{ github.workspace }}\dcmtk-${{ env.NOW }}-${{ env.COMMIT_SHORT_SHA }} ${{ github.workspace }}
+ cmake -G "Visual Studio 17 2022" -Ax64 -DDCMTK_MODULES:STR="ofstd;oflog;oficonv;dcmdata;dcmimgle;dcmimage;dcmjpeg;dcmjpls;dcmtls;dcmnet;dcmsr;dcmsign;dcmwlm;dcmqrdb;dcmpstat;dcmrt;dcmiod;dcmfg;dcmseg;dcmtract;dcmpmap;dcmect;dcmapps" -DDCMTK_ENABLE_BUILTIN_OFICONV_DATA:BOOL=On -DBUILD_SHARED_LIBS:BOOL=ON -DDCMTK_SUPPORT_LIBRARIES_DIR:PATH=c:\dcmtk_support\libs -DCMAKE_INSTALL_PREFIX:PATH=${{ github.workspace }}\dcmtk-${{ env.NOW }}-${{ env.COMMIT_SHORT_SHA }} ${{ github.workspace }}
- name: Build dcmtk
run: |
runs-on: windows-latest
timeout-minutes: 5
- # Only run if the event is not a pull request and the repository owner is DCMTK.
+ # Only run if the event is not a pull request and the repository owner is michaelonken.
# The latter is to prevent forks from publishing packages even if the owner's token
# would have sufficient privileges.
if: ${{ (github.event_name != 'pull_request') && (github.repository_owner == 'DCMTK')}}
--prerelease-packages-clear-pattern "dcmtk-*-win64.zip" `
--prerelease-packages-keep-pattern "*<COMMIT_SHORT_SHA>*" `
--prerelease-sha master `
- --token ${{ secrets.RELEASE_DCMTK_TOKEN }}
\ No newline at end of file
+ --token ${{ secrets.RELEASE_DCMTK_TOKEN }}
*.*~
*.bak
+# Ignore caches
+.cache
+
# Also ignore temporary directories
_*/
ofstd/tests/tehtestdire/
dcmdata/apps/dcm2xml
dcmdata/apps/dcmconv
dcmdata/apps/dcmcrle
+dcmdata/apps/dcmdecap
dcmdata/apps/dcmdrle
dcmdata/apps/dcmdump
+dcmdata/apps/dcmencap
dcmdata/apps/dcmftest
dcmdata/apps/dcmgpdir
dcmdata/apps/dcmodify
dcmdata/apps/dump2dcm
dcmdata/apps/img2dcm
+dcmdata/apps/json2dcm
dcmdata/apps/pdf2dcm
dcmdata/apps/stl2dcm
dcmdata/apps/xml2dcm
ANNOUNCEMENT
-Version 3.6.9 of the OFFIS DCMTK (DICOM toolkit) software is now available for
+Version 3.7.0 of the OFFIS DCMTK (DICOM ToolKit) software is now available for
public release. This release includes the following main changes over the
-previous version 3.6.8:
+previous version 3.6.9:
-- DCMTK 3.6.9 builds correctly on older and up-to-date versions of GNU gcc
- (9.5.0 to 14.2.0), Clang (14.0.6 to 18.1.8), Apple Clang (14.0.3 to 15.0.0),
+- DCMTK 3.7.0 builds correctly on older and up-to-date versions of GNU gcc
+ (10.5.0 to 14.2.0), Clang (14.0.6 to 18.1.8), Apple Clang (17.0.0),
and Microsoft Visual Studio (2017 to 2022).
- Tested with the following operating systems/environments:
- Android on arm64
- FreeBSD on x86_64
- - Linux on x86_64 and x86
+ - Linux on x86_64, x86 and s390x
- MacOS X on x86_64 and arm64
- NetBSD on x86_64
- OpenBSD on x86_64
- Updated DICOM data dictionary, list of SOP classes, well-known frame of
references, transfer syntaxes, code definitions, supported context group
- classes, and directory record types for DICOM standard release 2024e:
+ classes, and directory record types for DICOM standard release 2025e.
- - This also includes the latest attributes and SOP classes for the DICONDE
- standard, e.g. for thermography images (based on ASTM E3440).
+- Added initial support for the Deflated Image Frame Compression Transfer
+ Syntax, i.e. reading and writing of DICOM files and datasets that are
+ encoded with this new transfer syntax as well as basic network support.
- - Also updated the DICOMDIR generation code and tools accordingly.
+- Added support for the DICONDE Storage SOP Class for ultrasonic waveforms
+ introduced with DICOM 2025b (based on a revised version of ASTM E2663).
+- Added support for creating, writing and reading Labelmap Segmentation Storage
+ objects to the "dcmseg" module.
-- The new JPEG XL and HTJ2K transfer syntaxes as well as the encapsulated
- uncompressed transfer syntax are now supported for reading and writing, i.e.
- for both files and network transfer. However, encoders or decoders have not
- been implemented yet.
+- Added new command line tools "dcmencap" and "dcmdecap" that handle the
+ encapsulation and decapsulation of all currently defined Encapsulated
+ Document Storage SOP Classes in DICOM. The older tools "pdf2dcm", "cda2dcm",
+ "stl2dcm", "dcm2pdf" and "dcm2cda" are now deprecated and will be removed in
+ a future version of DCMTK.
-- Added new command line tool dcm2img that unifies and replaces the tools
- dcm2pnm, dcmj2pnm and dcml2pnm, and adds support for JPEG-LS as an export
- format for image files. The command line options are identical to the older
- tools, so that dcm2img can serve as a drop-in replacement:
+- Added new command line tool "json2dcm" that converts the contents of a DICOM
+ dataset in JSON encoding to a binary DICOM file or dataset. The JSON
+ document is expected to conform to the "DICOM JSON Model" as defined in
+ DICOM Part 18, Section F.
- - By default, the new command line tool determines the output format
- automatically based on the extension of the output filename.
+- The command line tool "dcm2json" can now create BulkDataURIs and related bulk
+ data files.
- - The deprecated command line tools were replaced by stubs, which are provided
- for the user's convenience, but will be removed with a future release.
+- Improved the handling of JPEG image files as input to "img2dcm". Several
+ special cases such as different types of component subsampling, or lossy JPEG
+ images in RGB or CMYK color (instead of YCbCr) are now correctly handled.
-- Added new command line tool dcm2cda that extracts a CDA document from a DICOM
- Encapsulated CDA Storage SOP Instance and stores it in a separate file.
+- The "storescp" tool can now limit the number of network associations handled
+ in parallel when operating in "fork mode", on all supported platforms.
-- Replaced command line tool dcmgpdir by a stub that calls the more
- comprehensive command line tool dcmmkdir.
+- Enhanced Specific Character Set support of the command line tool "dcm2xml"
+ when converting DICOMDIR files.
-- Further enhanced and updated DICOM Structured Reporting (SR) module "dcmsr":
+- Added support for the optional Patient's Age attribute from the Patient
+ Study Module to the "dcmsr" module. This attribute is now written to and
+ read from a DICOM dataset as well as to/from the "dcmsr"-specific XML
+ document format (see "dsr2xml.xsd").
- - Added support for the new Waveform Annotation SR IOD (introduced with
- Supplement 239).
+- Enhanced support for TLS in command line tools "dcmqrscp" and "movescu".
+ Query/Retrieve can now be completely performed over TLS.
- - Made URL prefix for hyperlinks to composite objects configurable.
+- Added support for IPv6 in DCMTK's association acceptors. The support for
+ DICOM network connections over IPv6 is now considered complete. Both
+ association requestors and association acceptors can choose between IPv4
+ only, IPv6 only, and dual-stack mode. The default behavior of the command
+ line tools is unchanged (i.e. IPv4 only.)
- - Updated code definitions and supported context group classes (see above).
+- Added APIs that allows the user to set the Implementation Class UID and
+ Implementation Version Name at runtime while writing a DICOM file, processing
+ an incoming network association request or configuring an outgoing network
+ association request.
- - Fixed issue with various IOD constraint checkers (see CP-2084).
+- Added "putAndInsertXXX()" helper methods for the still rather new 64-bit VRs
+ "SV", "UV" and "OV" to the "DcmItem" class.
-- Added IPv6 support to DCMTK's association requestors. All DCMTK "client"
- applications that only request outgoing DICOM network associations can now
- explicitly select the protocol version to be used. IPv6 support is not yet
- implemented for association acceptors ("server" applications).
+- Improved handling of invalid DICOM images when processing with the
+ "DicomImage" class or the "dcm2img" command line tool.
-- Various TLS enhancements:
+- Improved performance of the "DcmList" class that is used internally for the
+ DICOM dataset parser.
- - Added TLS support to the command line tools dcmqrscp and getscu.
+- Further clean-up of configure tests that checked for features that are not
+ used anymore in DCMTK or that are not in use anymore on any of the supported
+ operating systems (e.g. pre-POSIX APIs and header files).
- - Added support for the Modified BCP 195 RFC 8996 TLS Profile.
-
- - Added new command line option --list-profiles to all TLS-enabled tools.
- This option prints a list of the TLS Secure Transport Connection Profiles
- supported.
-
- - Removed support for OpenSSL 1.0.2 and 1.1.0 and added support for OpenSSL
- 3.1.0 to 3.4.0.
-
-- Extended central DCMTK data structure where all SOP Classes are defined with
- their associated properties, e.g. type and sub-type.
-
-- Largely enhanced basic transfer syntax class DcmXfer, e.g. to distinguish
- more clearly between encapsulation and compression. Please note that some of
- the old methods have been deprecated and will be removed in a future release.
-
-- Enhanced performance of OFGlobal class, especially when used in applications
- with many threads that read global objects of this class concurrently.
-
-- New, fully standards compliant implementations of OFStandard::atof() and
- OFStandard::ftoa(), DCMTK's locale independent conversion routines between
- floating point numbers and text.
-
-- Removed support for ICU-based character set conversion. Since the oficonv
- module in DCMTK supports all DICOM Specific Character Sets, the ICU support,
- which was never complete, has been removed.
-
-- DCMTK now requires compilers to provide conformance to C++98 and supports
- compilation with newer C++ versions up to C++20, which can be enabled via
- CMake's CMAKE_CXX_STANDARD variable. By default, C++11 is now enabled on
- compilers that support this.
-
-- CMake-related enhancements and other changes:
-
- - The configure process now respects CMake's CMAKE_CROSSCOMPILING_EMULATOR
- variable.
-
- - Exposed the CMAKE_DEBUG_POSTFIX variable to the user. There are extra
- options to also enable the postfix for Windows DLLs as well as executables.
-
-- Many configure tests related to outdated compilers or libraries were removed,
- thus significantly speeding up the configuration process.
-
-- Fixed binary segmentations with certain dimensions (some cases where number
- of total bits per frame is not divisible by 8) that were broken when being
- serialized into a dataset.
-
-- Fixed various other issues that occurred after the official 3.6.8 release,
+- Fixed various other issues that occurred after the official 3.6.9 release,
and further improved the performance. See CHANGES file for details.
Many people have contributed to this new release of DCMTK, appearing here in
alphabetical order. Thank you very much for your support!
- Christian Wetzel <wetzel@phoenix-pacs.de>
- David Gobbi <david.gobbi@gmail.com>
- David Seifert <soap@gentoo.org>
- Giulio Simonetti <giulio.simonetti@datamind.biz>
- Helmut Steiner <helmut@shl.at>
- Jean Pierre Bassenge <jp.bassenge@fiagon.com>
+ Ben Chen <Ben.Chen@intusurg.com>
+ Chuang Zhao <zhaocccchuang@163.com>
+ Ding zhengzheng <xiaozheng.ding399@gmail.com>
+ Drak <dr4k.sec@gmail.com>
+ Emmanuel Tacheau of the Cisco Talos team <vulndiscovery@external.cisco.com>
Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
- Jesper Alf Dam <Jesper.Dam@mi.medical.canon>
- Kevin Leonardic <kevin@leonardic.de>
- Marcel Pham <Marcel.Pham@examion.com>
- Mario Galijot <mario@salaourn.com>
- Markus Sabin <Markus.Sabin@soft-gate.de>
- Martin Zeiser of the Cisco Talos team <vulndiscovery@external.cisco.com>
+ Jez Cooke <jez.cooke@hamamatsu.eu>
+ Kade Rashid <kade.rashid@hamamatsu.eu>
+ Khang Tran <khangthk@gmail.com>
Mathieu Malaterre <mathieu.malaterre@gmail.com>
- Matt McCormick <matt.mccormick@kitware.com>
- Melanie Michels <melanie.michels@snkeos.com>
- Nils Bars <nils.bars@rub.de>
- Peter Klotz <peter.klotz@siemens-healthineers.com>
- Phileas Lebada <phileas@contextflow.com>
- Piotr Batko <Piotr.Batko@gehealthcare.com>
- Sam James <sam@gentoo.org>
+ Matt Hancock <mhancock@innolitics.com>
+ Oliver Klerx <klerx@phoenix-pacs.de>
+ Simeon Stoykov <simeon@microdicom.com>
Sobhita Mercy <sobhitamercy@gmail.com>
- Yoshinaga Kosuke <kosuke.yoshinaga@goodmankk.com>
+ Vasyl Horbatenko (GitHub user doskachok)
+ Zou Dikai <zoudikai@outlook.com>
- DCMTK forum users "andreasb", "Fabian Guenther", "nbeck", "Oleh", "saltcreek"
+ DCMTK forum users "cschreib", "hapap", "OliWe", "pierrechatelier",
+ "pintagliata", "saltcreek" and "Shaeto"
- GitHub users "akaraivanov", "bananabr", "khangthk", "luissantosHCIT",
- "malaterre", "mrbean-bremen", "percontation", "thewtex"
+ GitHub users "luk1337", "mrbean-bremen", "nbeck-SMT", "Oss-Auditor",
+ "parasite-lost", "reunanen" and "Vovasch"
Members of the DCMTK Team who have worked on this release are:
https://dicom.offis.de/dcmtk or https://www.dcmtk.org/
-OFFIS e.V., Oldenburg, Germany, 2024-12-10
+OFFIS e.V., Oldenburg, Germany, 2025-12-15
message(STATUS "Info: DCMTK PNG support will be enabled")
set(WITH_LIBPNG 1)
include_directories(${PNG_INCLUDE_DIR})
- set(LIBPNG_LIBS ${PNG_LIBRARY})
+ set(LIBPNG_LIBS ${PNG_LIBRARY} ${LIBPNG_EXTRA_LIBS_STATIC})
endif()
endif()
set(LIBXML_INCDIR "${WITH_LIBXMLINC}/include")
set(LIBXML_LIBDIR "${WITH_LIBXMLINC}/lib")
# libxml2 2.13 and newer require bcrypt.lib on Windows.
- set(LIBXML_LIBS bcrypt debug "${LIBXML_LIBDIR}/libxml2_d.lib" optimized "${LIBXML_LIBDIR}/libxml2_o.lib")
- if (EXISTS "${LIBXML_LIBDIR}/iconv_o.lib")
+ set(LIBXML_LIBS bcrypt debug "${LIBXML_LIBDIR}/libxml2_d.lib" optimized "${LIBXML_LIBDIR}/libxml2_o.lib" ${LIBXML2_EXTRA_LIBS_STATIC})
+ if(EXISTS "${LIBXML_LIBDIR}/iconv_o.lib")
set(LIBXML_LIBS ${LIBXML_LIBS} debug "${LIBXML_LIBDIR}/iconv_d.lib" optimized "${LIBXML_LIBDIR}/iconv_o.lib")
endif()
message(STATUS "Info: DCMTK XML support will be enabled")
if(WITH_LIBPNGINC)
set(LIBPNG_INCDIR "${WITH_LIBPNGINC}/include")
set(LIBPNG_LIBDIR "${WITH_LIBPNGINC}/lib")
- set(LIBPNG_LIBS debug "${LIBPNG_LIBDIR}/libpng_d.lib" optimized "${LIBPNG_LIBDIR}/libpng_o.lib")
+ set(LIBPNG_LIBS debug "${LIBPNG_LIBDIR}/libpng_d.lib" optimized "${LIBPNG_LIBDIR}/libpng_o.lib" ${LIBPNG_EXTRA_LIBS_STATIC})
message(STATUS "Info: DCMTK PNG support will be enabled")
set(WITH_LIBPNG 1)
else() # turn off library if library path not set
if(WITH_LIBTIFFINC)
set(LIBTIFF_INCDIR "${WITH_LIBTIFFINC}/include")
set(LIBTIFF_LIBDIR "${WITH_LIBTIFFINC}/lib")
- set(LIBTIFF_LIBS debug "${LIBTIFF_LIBDIR}/libtiff_d.lib" optimized "${LIBTIFF_LIBDIR}/libtiff_o.lib")
+ set(LIBTIFF_LIBS debug "${LIBTIFF_LIBDIR}/libtiff_d.lib" optimized "${LIBTIFF_LIBDIR}/libtiff_o.lib" ${TIFF_EXTRA_LIBS_STATIC})
message(STATUS "Info: DCMTK TIFF support will be enabled")
set(WITH_LIBTIFF 1)
else() # turn off library if library path not set
set(OPENSSL_INCDIR "${WITH_OPENSSLINC}/include")
set(OPENSSL_LIBDIR "${WITH_OPENSSLINC}/lib")
# starting with OpenSSL 1.1.0, the Windows crypt32 library is needed for a static link of OpenSSL.
- set(OPENSSL_LIBS "crypt32" debug "${OPENSSL_LIBDIR}/dcmtkssl_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkssl_o.lib" debug "${OPENSSL_LIBDIR}/dcmtkcrypto_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkcrypto_o.lib")
+ set(OPENSSL_LIBS "crypt32" debug "${OPENSSL_LIBDIR}/dcmtkssl_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkssl_o.lib" debug "${OPENSSL_LIBDIR}/dcmtkcrypto_d.lib" optimized "${OPENSSL_LIBDIR}/dcmtkcrypto_o.lib" ${OPENSSL_EXTRA_LIBS_STATIC})
set(TEMP_INCLUDES "${CMAKE_REQUIRED_INCLUDES}")
list(APPEND CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCDIR}")
CHECK_CXX_SOURCE_COMPILES("extern \"C\" {\n#include <openssl/ssl.h>\n}\nint main(){\n#if OPENSSL_VERSION_NUMBER < 0x10001000L\n#error OpenSSL too old\n#endif\n}\n" OPENSSL_VERSION_CHECK)
if(WITH_SNDFILEINC)
set(SNDFILE_INCDIR "${WITH_SNDFILEINC}/include")
set(SNDFILE_LIBDIR "${WITH_SNDFILEINC}/lib")
- set(SNDFILE_LIBS debug "${SNDFILE_LIBDIR}/libsndfile_d.lib" optimized "${SNDFILE_LIBDIR}/libsndfile_o.lib")
+ set(SNDFILE_LIBS debug "${SNDFILE_LIBDIR}/libsndfile_d.lib" optimized "${SNDFILE_LIBDIR}/libsndfile_o.lib" ${SNDFILE_EXTRA_LIBS_STATIC})
message(STATUS "Info: DCMTK SNDFILE support will be enabled")
set(WITH_SNDFILE 1)
else() # turn off library if library path not set
# Unfortunately, OpenJPEG uses a version number in the include path. This needs special handling.
file(GLOB OPENJPEG2_DIR "${WITH_OPENJPEGINC}/include/openjpeg*")
find_path(WITH_OPENJPEGINC1 "openjpeg.h" "${OPENJPEG2_DIR}" NO_DEFAULT_PATH)
- if ("${WITH_OPENJPEGINC1}" STREQUAL "WITH_OPENJPEGINC1-NOTFOUND")
+ if("${WITH_OPENJPEGINC1}" STREQUAL "WITH_OPENJPEGINC1-NOTFOUND")
message(STATUS "Info: DCMTK OpenJPEG support will be disabled because the header files were not found.")
set(DCMTK_WITH_OPENJPEG OFF CACHE BOOL "" FORCE)
set(WITH_OPENJPEG "")
else()
set(OPENJPEG_INCDIR "${WITH_OPENJPEGINC1}")
set(OPENJPEG_LIBDIR "${WITH_OPENJPEGINC}/lib")
- set(OPENJPEG_LIBS debug "${OPENJPEG_LIBDIR}/openjp2_d.lib" optimized "${OPENJPEG_LIBDIR}/openjp2_o.lib")
+ set(OPENJPEG_LIBS debug "${OPENJPEG_LIBDIR}/openjp2_d.lib" optimized "${OPENJPEG_LIBDIR}/openjp2_o.lib" ${OPENJPEG_EXTRA_LIBS_STATIC})
message(STATUS "Info: DCMTK OpenJPEG support will be enabled")
set(WITH_OPENJPEG 1)
endif()
#
# Restore the required settings of the CMake configuration step
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.7.0...4.2.0 FATAL_ERROR)
set(CMAKE_COMMAND "@CMAKE_COMMAND@")
set(CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@")
set(CMAKE_CURRENT_BINARY_DIR "@CMAKE_BINARY_DIR@")
set(CMAKE_HOST_SYSTEM "@CMAKE_HOST_SYSTEM@")
set(DCMTK_CMAKE_INCLUDE "@CMAKE_SOURCE_DIR@/@DCMTK_CMAKE_INCLUDE@")
set(DCMTK_TEST_EXECUTABLES "@DCMTK_TEST_EXECUTABLES@")
+set(DCMTK_TEST_EXECUTABLE_PATH "@DCMTK_TEST_EXECUTABLE_PATH@")
set(DCMTK_ALL_LIBRARIES "@DCMTK_ALL_LIBRARIES@")
set(DCMTK_LIBRARY_DEPENDENCIES "@DCMTK_LIBRARY_DEPENDENCIES@")
set(DCMTK_PACKAGE_VERSION "@DCMTK_PACKAGE_VERSION@")
set(DCMTK_ABI_VERSION "@DCMTK_ABI_VERSION@")
set(BUILD_SHARED_LIBS "@BUILD_SHARED_LIBS@")
set(DCMTK_DICOM_DICTIONARIES "@DCMTK_DICOM_DICTIONARIES@")
+set(DCMTK_ICONV_DATAFILES "@DCMTK_ICONV_DATAFILES@")
set(ANDROID "@ANDROID@")
+set(ANDROID_EMULATOR_PORT "@ANDROID_EMULATOR_PORT@")
set(ANDROID_ADB_PROGRAM "@ANDROID_ADB_PROGRAM@")
-set(ANDROID_ANDROID_PROGRAM "@ANDROID_ANDROID_PROGRAM@")
+set(ANDROID_AVDMANAGER_PROGRAM "@ANDROID_AVDMANAGER_PROGRAM@")
set(ANDROID_EMULATOR_PROGRAM "@ANDROID_EMULATOR_PROGRAM@")
set(ANDROID_EMULATOR_AVD "@ANDROID_EMULATOR_AVD@")
set(ANDROID_RUNTIME_LIBRARIES "@ANDROID_RUNTIME_LIBRARIES@")
${ANDROID_RUNTIME_LIBRARIES}
${DCMTK_LIBRARY_DEPENDENCIES}
${DCMTK_CREATED_SHARED_LIBRARIES}
- ${DCMTK_TEST_EXECUTABLES}
+ ${DCMTK_TEST_EXECUTABLE_PATH}
${DCMTK_DICOM_DICTIONARIES}
+ ${DCMTK_ICONV_DATAFILES}
DESTINATION ${ANDROID_TEMPORARY_FILES_LOCATION}
)
# Set executable permissions
-foreach(TEST_EXECUTABLE ${DCMTK_TEST_EXECUTABLES})
+foreach(TEST_EXECUTABLE ${DCMTK_TEST_EXECUTABLE_PATH})
get_filename_component(NAME "${TEST_EXECUTABLE}" NAME)
DCMTK_ANDROID_SHELL(DCMTK_ANDROID_EMULATOR_INSTANCE
COMMAND chmod 755 "${ANDROID_TEMPORARY_FILES_LOCATION}/${NAME}"
# Run the actual testcase on the remote device
DCMTK_ANDROID_SHELL(DCMTK_ANDROID_EMULATOR_INSTANCE
- COMMAND "LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:${ANDROID_TEMPORARY_FILES_LOCATION}" "DCMDICTPATH=${DCMDICTPATH}" "${DCMTK_CTEST_TESTCASE_COMMAND}" $ENV{DCMTK_CTEST_EXTRA_ARGUMENTS} "${DCMTK_CTEST_TEST_NAME}"
+ COMMAND "LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:${ANDROID_TEMPORARY_FILES_LOCATION}" "DCMDICTPATH=${DCMDICTPATH}" "DCMICONVPATH=${DCMICONVPATH}" "${DCMTK_CTEST_TESTCASE_COMMAND}" $ENV{DCMTK_CTEST_EXTRA_ARGUMENTS} "${DCMTK_CTEST_TEST_NAME}"
WORKING_DIRECTORY "${ANDROID_TEMPORARY_FILES_LOCATION}"
RESULT_VARIABLE RESULT
)
set(DCMTK_ENABLE_LFS @DCMTK_ENABLE_LFS@)
set(DCMTK_ENABLE_CHARSET_CONVERSION @DCMTK_ENABLE_CHARSET_CONVERSION@)
-
# CMake builtins
set(DCMTK_CMAKE_BUILD_TYPE @CMAKE_BUILD_TYPE@)
set(DCMTK_CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@")
set(DCMTK_CMAKE_EXE_LINKER_FLAGS_MINSIZEREL @CMAKE_EXE_LINKER_FLAGS_MINSIZEREL@)
set(DCMTK_CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO @CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO@)
-set(DCMTK_CMAKE_INSTALL_BINDIR @CMAKE_INSTALL_BINDIR@)
-set(DCMTK_CMAKE_INSTALL_SYSCONFDIR @CMAKE_INSTALL_SYSCONFDIR@)
-set(DCMTK_CMAKE_INSTALL_INCLUDEDIR @CMAKE_INSTALL_INCLUDEDIR@)
-set(DCMTK_CMAKE_INSTALL_LIBDIR @CMAKE_INSTALL_LIBDIR@)
-set(DCMTK_CMAKE_INSTALL_DATAROOTDIR @CMAKE_INSTALL_DATAROOTDIR@)
+# DCMTK installation directories
+set(DCMTK_CMAKE_INSTALL_BINDIR "@CMAKE_INSTALL_BINDIR@")
+set(DCMTK_CMAKE_INSTALL_SYSCONFDIR "@CMAKE_INSTALL_SYSCONFDIR@")
+set(DCMTK_CMAKE_INSTALL_INCLUDEDIR "@CMAKE_INSTALL_INCLUDEDIR@")
+set(DCMTK_CMAKE_INSTALL_LIBDIR "@CMAKE_INSTALL_LIBDIR@")
+set(DCMTK_CMAKE_INSTALL_DATAROOTDIR "@CMAKE_INSTALL_DATAROOTDIR@")
+set(DCMTK_CMAKE_INSTALL_DATADIR "@CMAKE_INSTALL_DATADIR@")
+set(DCMTK_CMAKE_INSTALL_DOCDIR "@CMAKE_INSTALL_DOCDIR@")
set(DCMTK_CMAKE_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@")
-
SET_AND_CHECK(DCMTK_TARGETS "@PACKAGE_DCMTK_CMKDIR_CONFIG@/DCMTKTargets.cmake")
@DCMTK_CONFIG_CODE@
# Define the complete package version name that will be used as a subdirectory
# name for the installation of configuration files, data files and documents.
-if (DCMTK_PACKAGE_VERSION_SUFFIX STREQUAL "+")
+if(DCMTK_PACKAGE_VERSION_SUFFIX STREQUAL "+")
# development version
set(DCMTK_COMPLETE_PACKAGE_VERSION "${DCMTK_PACKAGE_VERSION}-${DCMTK_PACKAGE_DATE}")
else()
endif()
# Check the sizes of various types
-include (CheckTypeSize)
-CHECK_TYPE_SIZE("double" SIZEOF_DOUBLE)
-CHECK_TYPE_SIZE("float" SIZEOF_FLOAT)
+include(CheckTypeSize)
CHECK_TYPE_SIZE("int" SIZEOF_INT)
CHECK_TYPE_SIZE("long" SIZEOF_LONG)
-CHECK_TYPE_SIZE("short" SIZEOF_SHORT)
CHECK_TYPE_SIZE("void*" SIZEOF_VOID_P)
# Check for include files, libraries, and functions
CHECK_INCLUDE_FILE_CXX("cstdint" HAVE_CSTDINT)
CHECK_INCLUDE_FILE_CXX("dirent.h" HAVE_DIRENT_H)
CHECK_INCLUDE_FILE_CXX("err.h" HAVE_ERR_H)
- CHECK_INCLUDE_FILE_CXX("fcntl.h" HAVE_FCNTL_H)
CHECK_INCLUDE_FILE_CXX("fnmatch.h" HAVE_FNMATCH_H)
CHECK_INCLUDE_FILE_CXX("grp.h" HAVE_GRP_H)
CHECK_INCLUDE_FILE_CXX("ieeefp.h" HAVE_IEEEFP_H)
CHECK_INCLUDE_FILE_CXX("io.h" HAVE_IO_H)
CHECK_INCLUDE_FILE_CXX("langinfo.h" HAVE_LANGINFO_H)
CHECK_INCLUDE_FILE_CXX("libc.h" HAVE_LIBC_H)
- CHECK_INCLUDE_FILE_CXX("malloc.h" HAVE_MALLOC_H)
CHECK_INCLUDE_FILE_CXX("mqueue.h" HAVE_MQUEUE_H)
CHECK_INCLUDE_FILE_CXX("netdb.h" HAVE_NETDB_H)
CHECK_INCLUDE_FILE_CXX("png.h" HAVE_PNG_H)
CHECK_INCLUDE_FILE_CXX("pthread.h" HAVE_PTHREAD_H)
CHECK_INCLUDE_FILE_CXX("pwd.h" HAVE_PWD_H)
CHECK_INCLUDE_FILE_CXX("semaphore.h" HAVE_SEMAPHORE_H)
- CHECK_INCLUDE_FILE_CXX("stdint.h" HAVE_STDINT_H)
CHECK_INCLUDE_FILE_CXX("strings.h" HAVE_STRINGS_H)
CHECK_INCLUDE_FILE_CXX("synch.h" HAVE_SYNCH_H)
CHECK_INCLUDE_FILE_CXX("sys/dir.h" HAVE_SYS_DIR_H)
CHECK_INCLUDE_FILE_CXX("sys/resource.h" HAVE_SYS_RESOURCE_H)
CHECK_INCLUDE_FILE_CXX("sys/select.h" HAVE_SYS_SELECT_H)
CHECK_INCLUDE_FILE_CXX("sys/socket.h" HAVE_SYS_SOCKET_H)
- CHECK_INCLUDE_FILE_CXX("sys/stat.h" HAVE_SYS_STAT_H)
CHECK_INCLUDE_FILE_CXX("sys/syscall.h" HAVE_SYS_SYSCALL_H)
CHECK_INCLUDE_FILE_CXX("sys/systeminfo.h" HAVE_SYS_SYSTEMINFO_H)
CHECK_INCLUDE_FILE_CXX("sys/time.h" HAVE_SYS_TIME_H)
CHECK_INCLUDE_FILE_CXX("sys/timeb.h" HAVE_SYS_TIMEB_H)
- CHECK_INCLUDE_FILE_CXX("sys/types.h" HAVE_SYS_TYPES_H)
CHECK_INCLUDE_FILE_CXX("sys/un.h" HAVE_SYS_UN_H)
CHECK_INCLUDE_FILE_CXX("sys/utime.h" HAVE_SYS_UTIME_H)
CHECK_INCLUDE_FILE_CXX("sys/utsname.h" HAVE_SYS_UTSNAME_H)
CHECK_INCLUDE_FILE_CXX("unistd.h" HAVE_UNISTD_H)
CHECK_INCLUDE_FILE_CXX("unix.h" HAVE_UNIX_H)
CHECK_INCLUDE_FILE_CXX("utime.h" HAVE_UTIME_H)
- CHECK_INCLUDE_FILE_CXX("system_error" HAVE_SYSTEM_ERROR)
- CHECK_INCLUDE_FILE_CXX("tuple" HAVE_TUPLE)
CHECK_INCLUDE_FILE_CXX("type_traits" HAVE_TYPE_TRAITS)
CHECK_INCLUDE_FILE_CXX("atomic" HAVE_ATOMIC)
# This mimics the autoconf test. There are systems out there
# (e.g. FreeBSD and NeXT) where tcp.h can't be compiled on its own.
- set(TCP_H_DEPS "")
- if(HAVE_SYS_TYPES_H)
- # This one is needed to make FreeBSD happy
- set(TCP_H_DEPS "sys/types.h")
- endif()
+ # This one is needed to make FreeBSD happy
+ set(TCP_H_DEPS "sys/types.h")
CHECK_INCLUDE_FILES("${TCP_H_DEPS};netinet/in_systm.h" HAVE_NETINET_IN_SYSTM_H)
if(HAVE_NETINET_IN_SYSTM_H)
set(TCP_H_DEPS "${TCP_H_DEPS};netinet/in_systm.h")
set(HAVE_NO_TYPEDEF_PID_T TRUE)
else()
set(HAVE_NO_TYPEDEF_PID_T FALSE)
- if(NOT ${HAVE_SYS_TYPES_H})
- set(HAVE_NO_TYPEDEF_SSIZE_T TRUE)
- endif()
endif()
set(HEADERS)
endif()
set(HEADERS ${HEADERS} stdlib.h)
-
- if(HAVE_STDINT_H)
- set(HEADERS ${HEADERS} stdint.h)
- endif()
-
+ set(HEADERS ${HEADERS} stdint.h)
set(HEADERS ${HEADERS} stddef.h)
if(HAVE_NETDB_H)
set(HEADERS ${HEADERS} sys/resource.h)
endif()
- if(HAVE_SYS_TYPES_H)
- set(HEADERS ${HEADERS} sys/types.h)
- endif()
+ set(HEADERS ${HEADERS} sys/types.h)
if(HAVE_SYS_SOCKET_H)
set(HEADERS ${HEADERS} sys/socket.h)
endif()
- if(HAVE_SYS_STAT_H)
- set(HEADERS ${HEADERS} sys/stat.h)
- endif()
+ set(HEADERS ${HEADERS} sys/stat.h)
if(HAVE_SYS_TIMEB_H)
set(HEADERS ${HEADERS} sys/timeb.h)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} iphlpapi ws2_32 netapi32 wsock32)
endif()
- if(HAVE_FENV_H)
- set(HEADERS ${HEADERS} fenv.h)
- endif()
+ set(HEADERS ${HEADERS} fenv.h)
# std::vsnprintf and std::vsnprintf need the C++ version of the headers.
# We just assume they exist when the C version was found
CHECK_FUNCTION_EXISTS(_findfirst HAVE__FINDFIRST)
CHECK_FUNCTION_EXISTS(_set_output_format HAVE__SET_OUTPUT_FORMAT)
- CHECK_FUNCTION_EXISTS(access HAVE_ACCESS)
CHECK_FUNCTION_EXISTS(atoll HAVE_ATOLL)
- CHECK_FUNCTION_EXISTS(bcmp HAVE_BCMP)
CHECK_FUNCTION_EXISTS(cuserid HAVE_CUSERID)
CHECK_FUNCTION_EXISTS(fgetln HAVE_FGETLN)
- CHECK_FUNCTION_EXISTS(finite HAVE_FINITE)
CHECK_FUNCTION_EXISTS(flock HAVE_FLOCK)
CHECK_FUNCTION_EXISTS(fork HAVE_FORK)
CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO)
CHECK_FUNCTION_EXISTS(gethostid HAVE_GETHOSTID)
CHECK_FUNCTION_EXISTS(getlogin HAVE_GETLOGIN)
CHECK_FUNCTION_EXISTS(getlogin_r HAVE_GETLOGIN_R)
- CHECK_FUNCTION_EXISTS(getpid HAVE_GETPID)
CHECK_FUNCTION_EXISTS(getpwnam HAVE_GETPWNAM)
- CHECK_FUNCTION_EXISTS(getrusage HAVE_GETRUSAGE)
CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
CHECK_FUNCTION_EXISTS(getuid HAVE_GETUID)
CHECK_FUNCTION_EXISTS(gmtime_r HAVE_GMTIME_R)
- CHECK_FUNCTION_EXISTS(index HAVE_INDEX)
- CHECK_FUNCTION_EXISTS(itoa HAVE_ITOA)
- CHECK_FUNCTION_EXISTS(listen HAVE_LISTEN)
CHECK_FUNCTION_EXISTS(localtime_r HAVE_LOCALTIME_R)
CHECK_FUNCTION_EXISTS(lockf HAVE_LOCKF)
CHECK_FUNCTION_EXISTS(lstat HAVE_LSTAT)
CHECK_FUNCTION_EXISTS(malloc_debug HAVE_MALLOC_DEBUG)
CHECK_FUNCTION_EXISTS(mkstemp HAVE_MKSTEMP)
- CHECK_FUNCTION_EXISTS(mktemp HAVE_MKTEMP)
CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP)
- CHECK_FUNCTION_EXISTS(rindex HAVE_RINDEX)
CHECK_FUNCTION_EXISTS(setuid HAVE_SETUID)
CHECK_FUNCTION_EXISTS(sleep HAVE_SLEEP)
- CHECK_FUNCTION_EXISTS(stat HAVE_STAT)
- CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP)
CHECK_FUNCTION_EXISTS(strlcat HAVE_STRLCAT)
CHECK_FUNCTION_EXISTS(strlcpy HAVE_STRLCPY)
CHECK_FUNCTION_EXISTS(sysinfo HAVE_SYSINFO)
CHECK_SYMBOL_EXISTS(strcasestr "string.h" HAVE_PROTOTYPE_STRCASESTR)
- CHECK_FUNCTIONWITHHEADER_EXISTS(feenableexcept "${HEADERS}" HAVE_PROTOTYPE_FEENABLEEXCEPT)
- CHECK_FUNCTIONWITHHEADER_EXISTS(finite "${HEADERS}" HAVE_PROTOTYPE_FINITE)
- CHECK_FUNCTIONWITHHEADER_EXISTS("std::isinf(0.)" "${CXXHEADERS}" HAVE_PROTOTYPE_STD__ISINF)
- CHECK_FUNCTIONWITHHEADER_EXISTS("std::isnan(0.)" "${CXXHEADERS}" HAVE_PROTOTYPE_STD__ISNAN)
CHECK_FUNCTIONWITHHEADER_EXISTS(flock "${HEADERS}" HAVE_PROTOTYPE_FLOCK)
CHECK_FUNCTIONWITHHEADER_EXISTS(gethostbyname_r "${HEADERS}" HAVE_PROTOTYPE_GETHOSTBYNAME_R)
CHECK_FUNCTIONWITHHEADER_EXISTS(gethostbyaddr_r "${HEADERS}" HAVE_PROTOTYPE_GETHOSTBYADDR_R)
# not be defined in the standard C++ headers.
CHECK_FUNCTIONWITHHEADER_EXISTS(_vsnprintf_s "${HEADERS}" HAVE__VSNPRINTF_S)
CHECK_FUNCTIONWITHHEADER_EXISTS(vfprintf_s "${HEADERS}" HAVE_VFPRINTF_S)
- CHECK_FUNCTIONWITHHEADER_EXISTS(vsnprintf "${HEADERS}" HAVE_VSNPRINTF)
CHECK_FUNCTIONWITHHEADER_EXISTS(vsprintf_s "${HEADERS}" HAVE_VSPRINTF_S)
- CHECK_FUNCTIONWITHHEADER_EXISTS(std::vfprintf "${CXXHEADERS}" HAVE_PROTOTYPE_STD__VFPRINTF)
CHECK_FUNCTIONWITHHEADER_EXISTS(std::vsnprintf "${CXXHEADERS}" HAVE_PROTOTYPE_STD__VSNPRINTF)
CHECK_FUNCTIONWITHHEADER_EXISTS(_stricmp "${HEADERS}" HAVE_PROTOTYPE__STRICMP)
CHECK_FUNCTIONWITHHEADER_EXISTS(gettimeofday "${HEADERS}" HAVE_PROTOTYPE_GETTIMEOFDAY)
- CHECK_FUNCTIONWITHHEADER_EXISTS(mkstemp "${HEADERS}" HAVE_PROTOTYPE_MKSTEMP)
- CHECK_FUNCTIONWITHHEADER_EXISTS(mktemp "${HEADERS}" HAVE_PROTOTYPE_MKTEMP)
CHECK_FUNCTIONWITHHEADER_EXISTS(strcasecmp "${HEADERS}" HAVE_PROTOTYPE_STRCASECMP)
CHECK_FUNCTIONWITHHEADER_EXISTS(strncasecmp "${HEADERS}" HAVE_PROTOTYPE_STRNCASECMP)
CHECK_FUNCTIONWITHHEADER_EXISTS(strerror_r "${HEADERS}" HAVE_PROTOTYPE_STRERROR_R)
CHECK_FUNCTIONWITHHEADER_EXISTS("__sync_sub_and_fetch((int*)0,0)" "${HEADERS}" HAVE_SYNC_SUB_AND_FETCH)
CHECK_FUNCTIONWITHHEADER_EXISTS("InterlockedIncrement((long*)0)" "${HEADERS}" HAVE_INTERLOCKED_INCREMENT)
CHECK_FUNCTIONWITHHEADER_EXISTS("InterlockedDecrement((long*)0)" "${HEADERS}" HAVE_INTERLOCKED_DECREMENT)
- CHECK_FUNCTIONWITHHEADER_EXISTS("_fpclassf(0.0f)" "${HEADERS}" HAVE_PROTOTYPE__FPCLASSF)
CHECK_FUNCTIONWITHHEADER_EXISTS("getgrnam_r((char*)0,(group*)0,(char*)0,0,(group**)0)" "${HEADERS}" HAVE_GETGRNAM_R)
CHECK_FUNCTIONWITHHEADER_EXISTS("getpwnam_r((char*)0,(passwd*)0,(char*)0,0,(passwd**)0)" "${HEADERS}" HAVE_GETPWNAM_R)
CHECK_FUNCTIONWITHHEADER_EXISTS("readdir_r((DIR*)0,(dirent*)0,(dirent**)0)" "${HEADERS}" HAVE_READDIR_R)
CHECK_FUNCTIONWITHHEADER_EXISTS("readdir_r((DIR*)0,(dirent*)0)" "${HEADERS}" HAVE_OLD_READDIR_R)
- CHECK_FUNCTIONWITHHEADER_EXISTS(nanosleep "${HEADERS}" HAVE_PROTOTYPE_NANOSLEEP)
CHECK_FUNCTIONWITHHEADER_EXISTS("&passwd::pw_gecos" "${HEADERS}" HAVE_PASSWD_GECOS)
CHECK_FUNCTIONWITHHEADER_EXISTS("TryAcquireSRWLockShared((PSRWLOCK)0)" "${HEADERS}" HAVE_PROTOTYPE_TRYACQUIRESRWLOCKSHARED)
- # "definition" is an (exchangeable) identifier that is needed for successful compile test
- CHECK_FUNCTIONWITHHEADER_EXISTS("fp_except_t definition" "${HEADERS}" HAVE_DECLARATION_FP_EXCEPT_T)
# Check for some type definitions needed by JasPer and defines them if necessary
# Even if not functions but types are looked for, the script works fine.
# "definition" is an (exchangeable) identifier that is needed for successful compile test
- CHECK_FUNCTIONWITHHEADER_EXISTS("uchar definition" "${HEADERS}" HAVE_UCHAR_TYPEDEF)
- CHECK_FUNCTIONWITHHEADER_EXISTS("ushort definition" "${HEADERS}" HAVE_USHORT_TYPEDEF)
- CHECK_FUNCTIONWITHHEADER_EXISTS("uint definition" "${HEADERS}" HAVE_UINT_TYPEDEF)
- CHECK_FUNCTIONWITHHEADER_EXISTS("ulong definition" "${HEADERS}" HAVE_ULONG_TYPEDEF)
CHECK_FUNCTIONWITHHEADER_EXISTS("long long definition" "${HEADERS}" HAVE_LONG_LONG)
CHECK_FUNCTIONWITHHEADER_EXISTS("unsigned long long definition" "${HEADERS}" HAVE_UNSIGNED_LONG_LONG)
CHECK_FUNCTIONWITHHEADER_EXISTS("int64_t definition" "${HEADERS}" HAVE_INT64_T)
CHECK_FUNCTIONWITHHEADER_EXISTS("popen" "${HEADERS}" HAVE_POPEN)
CHECK_FUNCTIONWITHHEADER_EXISTS("pclose" "${HEADERS}" HAVE_PCLOSE)
- # Signal handling functions
- CHECK_FUNCTIONWITHHEADER_EXISTS("sigjmp_buf definition" "setjmp.h" HAVE_SIGJMP_BUF)
-
if(HAVE_LOCKF AND ANDROID)
# When Android introduced lockf, they forgot to put the constants like F_LOCK in the
# appropriate headers, this tests if they are defined and disables lockf if they are not
#include <pthread.h>
-int main ()
+int main()
{
pthread_t p;
unsigned long l = p;
DCMTK_CHECK_ENABLE_LFS()
-if(WIN32)
- # If someone can tell me how to convince TRY_COMPILE to link against winsock,
- # we could use tests for these. Until then, here is what would be the result:
- set(HAVE_INTP_ACCEPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument")
- set(HAVE_INTP_GETSOCKOPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument")
-else()
- # Check if socket functions accept an int*
- DCMTK_TRY_COMPILE(HAVE_INTP_SOCKET, "socket functions accept an int* argument"
- "
-#ifdef __cplusplus
-extern \"C\" {
-#endif
-#ifdef _WIN32
-/* Windows is pure evil */
-#include <windows.h>
-#else
-#include <sys/socket.h>
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int main()
-{
- int i;
- struct sockaddr *addr = 0;
- int addrlen = 0;
- int optlen = 0;
-
- i = accept(1, addr, &addrlen);
- i = getsockopt(0, 0, 0, 0, &optlen);
-
- return 0;
-}")
- if(HAVE_INTP_SOCKET)
- set(HAVE_INTP_ACCEPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument")
- set(HAVE_INTP_GETSOCKOPT 1 CACHE INTERNAL "Set if socket functions accept an int* argument")
- else()
- set(HAVE_INTP_ACCEPT 0 CACHE INTERNAL "Set if socket functions accept an int* argument")
- set(HAVE_INTP_GETSOCKOPT 0 CACHE INTERNAL "Set if socket functions accept an int* argument")
- endif()
-endif()
-
# Check for alignment query / specifier support
DCMTK_TRY_COMPILE(HAVE_GNU_ALIGNOF "__alignof__ is supported"
"int main()
return enable<sizeof(sfinae<test>(0)) == sizeof(yes_type)>::result;
}")
-DCMTK_TRY_COMPILE(HAVE_STD_NAMESPACE "ANSI standard C++ includes use std namespace"
- "#include <iostream>
-int main()
-{
- using namespace std;
- std::cout << endl;
- return 0;
-}")
-
-DCMTK_TRY_COMPILE(HAVE_STD__NOTHROW "the compiler supports std::nothrow"
- "#include <new>
-int main()
-{
- int* i = new (std::nothrow) int;
- return 0;
-}")
-
-DCMTK_TRY_COMPILE(HAVE_NOTHROW_DELETE "the compiler supports operator delete (std::nothrow)"
- "#include <new>
-int main()
-{
- int* i = 0;
- operator delete (i,std::nothrow);
- return 0;
-}")
-
DCMTK_TRY_COMPILE(HAVE_STATIC_ASSERT "the compiler supports static_assert"
"#include <cassert>
int main()
set(FORCE_MSVC_CPLUSPLUS_MACRO "")
if(MSVC)
if(NOT (MSVC_VERSION LESS 1910)) # VS 2017 and above
- set (FORCE_MSVC_CPLUSPLUS_MACRO "/Zc:__cplusplus")
+ set(FORCE_MSVC_CPLUSPLUS_MACRO "/Zc:__cplusplus")
endif()
endif()
endforeach()
endif()
+if(NOT HAVE_CXX11 AND NOT DCMTK_PERMIT_CXX98)
+ # Since the situation where the user has explicitly requested CMAKE_CXX_STANDARD=98
+ # has already been handled in dcmtkPrepare.cmake, we are apparently using a compiler
+ # that uses C++98 by default, and the user has not requested anything specific.
+ message(FATAL_ERROR "DCMTK will require C++11 or later in the future (which is apparently not supported by this compiler). Use cmake option -DDCMTK_PERMIT_CXX98=ON to override this error (for now).")
+endif()
if(CMAKE_CROSSCOMPILING)
set(DCMTK_CROSS_COMPILING ${CMAKE_CROSSCOMPILING})
string(REPLACE "\\" "\\\\" TEST_COMMAND "${TEST_COMMAND}")
elseif(ANDROID)
set(TEST_COMMAND "${ANDROID_TEMPORARY_FILES_LOCATION}/${MODULE}_tests")
+ set(MODULE_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${MODULE}_tests${CMAKE_EXECUTABLE_SUFFIX}")
+ list(APPEND DCMTK_TEST_EXECUTABLE_PATH "${MODULE_PATH}")
+ set(DCMTK_TEST_EXECUTABLE_PATH ${DCMTK_TEST_EXECUTABLE_PATH} CACHE INTERNAL "")
else()
# not reachable, handled by not defining DCMTK_RUN_CTEST_SCRIPT
endif()
# Basic version information
set(DCMTK_MAJOR_VERSION 3)
-set(DCMTK_MINOR_VERSION 6)
-set(DCMTK_BUILD_VERSION 9)
+set(DCMTK_MINOR_VERSION 7)
+set(DCMTK_BUILD_VERSION 0)
# The ABI is not guaranteed to be stable between different snapshots/releases,
# so this particular version number is increased for each snapshot or release.
-set(DCMTK_ABI_VERSION 19)
+set(DCMTK_ABI_VERSION 20)
# Package "release" settings (some are currently unused and, therefore, disabled)
set(DCMTK_PACKAGE_NAME "dcmtk")
-set(DCMTK_PACKAGE_DATE "2024-12-11")
+set(DCMTK_PACKAGE_DATE "2025-12-15")
set(DCMTK_PACKAGE_VERSION "${DCMTK_MAJOR_VERSION}.${DCMTK_MINOR_VERSION}.${DCMTK_BUILD_VERSION}")
set(DCMTK_PACKAGE_VERSION_NUMBER ${DCMTK_MAJOR_VERSION}${DCMTK_MINOR_VERSION}${DCMTK_BUILD_VERSION})
set(DCMTK_PACKAGE_VERSION_SUFFIX "")
option(DCMTK_LINK_STATIC "Statically link all libraries and tools with the runtime and third party libraries." OFF)
# Modify linker flags and libraries for static builds if enabled by the user
if(DCMTK_LINK_STATIC)
- if (NOT APPLE)
+ if(NOT APPLE)
# MacOS does not support static libraries. DCMTK_LINK_STATIC is still useful on
# macOS though, since it will create binaries that only depend on macOS's libc.
set(CMAKE_EXE_LINKER_FLAGS "-static")
option(DCMTK_PORTABLE_LINUX_BINARIES "Create ELF binaries while statically linking all third party libraries and libstdc++." OFF)
if(DCMTK_PORTABLE_LINUX_BINARIES)
- if (DCMTK_LINK_STATIC)
+ if(DCMTK_LINK_STATIC)
message(FATAL_ERROR "Options DCMTK_LINK_STATIC and DCMTK_PORTABLE_LINUX_BINARIES are mutually exclusive.")
endif()
# only use static versions of third party libraries
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
# When using gcc and clang, use the static version of libgcc/libstdc++.
- if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
+ if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
(CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang") OR
# This should possibly be enhanced by using find_package() at some point. The best solution
# would probably be to compile all third-party libraries ourself.
if(DCMTK_LINK_STATIC OR DCMTK_PORTABLE_LINUX_BINARIES)
+ get_static_library("STATIC_ZLIB" "libz.a")
+ set(LIBPNG_EXTRA_LIBS_STATIC "${STATIC_ZLIB}")
get_static_library("STATIC_DL" "libdl.a")
get_static_library("STATIC_LZMA" "liblzma.a")
- get_static_library("STATIC_ZLIB" "libz.a")
- set(LIBXML2_EXTRA_LIBS_STATIC "${STATIC_LZMA}" "${STATIC_ZLIB}" "${STATIC_DL}")
+
+ # On Debian Linux, libxml2 depends on libicu. We do not want that dependency in our
+ # own builds since it massively increases the size of the executable binaries.
+ # If you still want to try, then enable the following two statements:
+ #
+ # get_static_library("STATIC_ICUUC" "libicuuc.a")
+ # get_static_library("STATIC_ICUDATA" "libicudata.a")
+
+ set(LIBXML2_EXTRA_LIBS_STATIC "${STATIC_LZMA}" "${STATIC_ZLIB}" "${STATIC_DL}" "${STATIC_ICUUC}" "${STATIC_ICUDATA}")
get_static_library("STATIC_PTHREAD" "libpthread.a")
set(OPENJPEG_EXTRA_LIBS_STATIC "${STATIC_PTHREAD}")
set(OPENSSL_EXTRA_LIBS_STATIC "${STATIC_DL}")
get_static_library("STATIC_JBIG" "libjbig.a")
get_static_library("STATIC_JPEG" "libjpeg.a")
get_static_library("STATIC_DEFLATE" "libdeflate.a")
- set(TIFF_EXTRA_LIBS_STATIC "${STATIC_WEBP}" "${STATIC_ZSTD}" "${STATIC_LZMA}" "${STATIC_JBIG}" "${STATIC_JBIG}" "${STATIC_DEFLATE}" "${STATIC_ZLIB}")
+
+ # On Debian Linux, libtiff depends on libLerc. We do not need that dependency in our
+ # own builds. If want to use Debian's libtiff, then enable the following statement:
+ #
+ # get_static_library("STATIC_LIBLERC" "libLerc.a")
+
+ set(TIFF_EXTRA_LIBS_STATIC "${STATIC_WEBP}" "${STATIC_ZSTD}" "${STATIC_LZMA}" "${STATIC_JBIG}" "${STATIC_JBIG}" "${STATIC_DEFLATE}" "${STATIC_ZLIB}" "${STATIC_LIBLERC}")
get_static_library("STATIC_NSL" "libnsl.a")
set(WRAP_EXTRA_LIBS_STATIC "${STATIC_NSL}")
else()
+ set(LIBPNG_EXTRA_LIBS_STATIC)
set(LIBXML2_EXTRA_LIBS_STATIC)
set(OPENJPEG_EXTRA_LIBS_STATIC)
set(OPENSSL_EXTRA_LIBS_STATIC)
option(DCMTK_WITH_XML "Configure DCMTK with support for XML." ON)
option(DCMTK_WITH_ZLIB "Configure DCMTK with support for ZLIB." ON)
option(DCMTK_WITH_OPENSSL "Configure DCMTK with support for OPENSSL." ON)
-option(DCMTK_WITH_SNDFILE "Configure DCMTK with support for SNDFILE." ON)
+option(DCMTK_WITH_SNDFILE "Configure DCMTK with support for SNDFILE." OFF)
option(DCMTK_WITH_ICONV "Configure DCMTK with support for ICONV." ON)
if(NOT WIN32)
option(DCMTK_WITH_WRAP "Configure DCMTK with support for WRAP." ON)
endif()
set(DCMTK_DEFAULT_DICT "${DCMTK_DEFAULT_DICT_DEFAULT}" CACHE STRING "Denotes whether DCMTK will use built-in (compiled-in), external (file), or no default dictionary on startup")
set_property(CACHE DCMTK_DEFAULT_DICT PROPERTY STRINGS builtin external none)
-if (DCMTK_DEFAULT_DICT EQUAL "none")
+if(DCMTK_DEFAULT_DICT EQUAL "none")
message(WARNING "Denotes whether DCMTK will use built-in (compiled-in), external (file), or no default dictionary on startup")
endif()
# Declare the option DCMTK_ENABLE_BUILTIN_OFICONV_DATA, which by default is ON when
# we are compiling shared libraries.
-if (BUILD_SHARED_LIBS)
+if(BUILD_SHARED_LIBS)
option(DCMTK_ENABLE_BUILTIN_OFICONV_DATA "Embed oficonv data files into oficonv library" ON)
else()
option(DCMTK_ENABLE_BUILTIN_OFICONV_DATA "Embed oficonv data files into oficonv library" OFF)
endif()
# evaluate the option DCMTK_ENABLE_BUILTIN_OFICONV_DATA
-if (DCMTK_ENABLE_BUILTIN_OFICONV_DATA)
+if(DCMTK_ENABLE_BUILTIN_OFICONV_DATA)
add_definitions(-DDCMTK_ENABLE_BUILTIN_OFICONV_DATA)
endif()
if(WIN32)
option(DCMTK_OVERWRITE_WIN32_COMPILER_FLAGS "Modify the default compiler flags selected by CMake." ON)
option(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL "Compile DCMTK using the Multithreaded DLL runtime library." OFF)
- if (BUILD_SHARED_LIBS)
+ if(BUILD_SHARED_LIBS)
set(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL ON)
endif()
else()
endif()
if(WIN32 AND CMAKE_GENERATOR MATCHES "Visual Studio .*|NMake .*")
- if (POLICY CMP0091)
+ if(POLICY CMP0091)
# CMake 3.15 and newer use CMAKE_MSVC_RUNTIME_LIBRARY to select
# the MSVC runtime library
if(DCMTK_COMPILE_WIN32_MULTITHREADED_DLL OR BUILD_SHARED_LIBS)
endif()
# When compiling with IBM xlC, add flags to suppress some noisy C++ warnings
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "XL")
+ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "XL")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qsuppress=1500-029:1500-030")
endif()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
+option(DCMTK_PERMIT_CXX98 "Permit (deprecated) compilation with C++98 language standard. This will cease to function in a future DCMTK release." OFF)
+
# If desired C++ standard is at least C++11, set DCMTK_MODERN_CXX_STANDARD to true
# and remember it in global property DCMTK_MODERN_CXX_STANDARD.
# This is later evaluated in GenerateDCMTKConfigure.cmake in order to check
# whether the compiler actually supports the required C++ standards up to the
# version specified in CMAKE_CXX_STANDARD. Finally, the highest C++ version
# (<= CMAKE_CXX_STANDARD) will be selected that the compiler actually supports.
-if (NOT DEFINED CMAKE_CXX_STANDARD)
+if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
set(DCMTK_MODERN_CXX_STANDARD TRUE)
+elseif(CMAKE_CXX_STANDARD MATCHES "^9[0-9]?$" AND NOT DCMTK_PERMIT_CXX98)
+ message(FATAL_ERROR "DCMTK will require C++11 or later in the future. Use cmake option -DDCMTK_PERMIT_CXX98=ON to override this error (for now)")
elseif(CMAKE_CXX_STANDARD MATCHES "^9[0-9]?$")
set(DCMTK_MODERN_CXX_STANDARD FALSE)
- message(WARNING "DCMTK will require C++11 or later in the future.")
+ message(WARNING "DCMTK will require C++11 or later in the future, continuing for now.")
elseif(CMAKE_CXX_STANDARD GREATER 20)
MESSAGE(WARNING "DCMTK is only known to compile for C++ versions <= 20 (C++${CMAKE_CXX_STANDARD} requested).")
set(DCMTK_MODERN_CXX_STANDARD TRUE)
else() # CMAKE_CXX_STANDARD is 11, 14, 17 or 20
set(DCMTK_MODERN_CXX_STANDARD TRUE)
endif()
+
define_property(GLOBAL PROPERTY DCMTK_MODERN_CXX_STANDARD
BRIEF_DOCS "TRUE when compiling C++11 (or newer) code."
FULL_DOCS "TRUE when the compiler does support and is configured for C++11 or a later C++ standard."
)
+
# Remember globally that we use at least C++11
set_property(GLOBAL PROPERTY DCMTK_MODERN_CXX_STANDARD ${DCMTK_MODERN_CXX_STANDARD})
# Build global list of all modern C++ standard versions supported so far
add_compile_options("/W4")
else()
# Add -Wall to the compiler flags if we are compiling with gcc or Clang.
- if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
- (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR
- (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
- (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang") OR
- (CMAKE_CXX_COMPILER_ID STREQUAL "XLClang"))
- add_compile_options("-Wall")
+ if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang") OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "XLClang"))
+ add_compile_options("-Wall")
endif()
endif()
endif()
endfunction()
-DCMTK_TEST_SOCKET_LIBRARY(nsl "gethostbyname")
-DCMTK_TEST_SOCKET_LIBRARY(socket "socket")
+if(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_SYSTEM_VERSION VERSION_LESS "11.4")
+ DCMTK_TEST_SOCKET_LIBRARY(nsl "gethostbyname")
+ DCMTK_TEST_SOCKET_LIBRARY(socket "socket")
+endif()
#-----------------------------------------------------------------------------
# Test if SunPro compiler and add features
# * STOPPED - the emulated device has been
# shutdown or is currently being
# shutdown
-# EMULATOR_UUID: a generated ID to identify the emulator
-# instance. Meant to prevent accessing the wrong device
-# in case multiple Android devices are accessible.
# EMULATOR_NAME: the name of the emulator instance.
# all running emulator instances are named by the SDK
-# in a locally unique fashion. The name will only be
-# available in case the state is 'RUNNING', since
-# only the name of running devices can be retrieved
-# by UUID matching.
+# in a locally unique fashion from the provided port.
# An emulator instance is accessed by the different
# tools of the NDK (e. g. 'adb') by referring to the
# instance with the value of EMULATOR_NAME.
# individual components.
# VAR - the emulator instance handle object to unpack
# EMULATOR_STATE - will contain the emulators state
-# EMULATOR_UUID - will contain the generated UUID that
-# identifies the emulator instance
# EMULATOR_NAME - will contain the instance name, required
# to access the emulator via 'adb' etc.
-# All three outputs will be unset if the object in VAR
+# All two outputs will be unset if the object in VAR
# is not a valid emulator instance handle.
# All additional arguments will be ignored.
#
macro(DCMTK_ANDROID_GET_OBJECT_PROPERTIES VAR)
list(LENGTH ${VAR} ${VAR}_LENGTH)
- if(${VAR}_LENGTH EQUAL 3)
+ if(${VAR}_LENGTH EQUAL 2)
list(GET ${VAR} 0 EMULATOR_STATE)
- list(GET ${VAR} 1 EMULATOR_UUID)
- list(GET ${VAR} 2 EMULATOR_NAME)
+ list(GET ${VAR} 1 EMULATOR_NAME)
else()
unset(EMULATOR_STATE)
- unset(EMULATOR_UUID)
unset(EMULATOR_NAME)
endif()
endmacro()
# VAR - the name of the variable that shall contain the
# resulting instance handle object.
# EMULATOR_STATE - the state to set
-# EMULATOR_UUID - the UUID to set
# EMULATOR_NAME - the name to set
# All additional arguments will be ignored.
#
-macro(DCMTK_ANDROID_SET_OBJECT_PROPERTIES VAR EMULATOR_STATE EMULATOR_UUID EMULATOR_NAME)
- set(${VAR} "${EMULATOR_STATE}" "${EMULATOR_UUID}" "${EMULATOR_NAME}" CACHE INTERNAL "")
+macro(DCMTK_ANDROID_SET_OBJECT_PROPERTIES VAR EMULATOR_STATE EMULATOR_NAME)
+ set(${VAR} "${EMULATOR_STATE}" "${EMULATOR_NAME}" CACHE INTERNAL "")
endmacro()
#
#
function(DCMTK_SETUP_ANDROID_EMULATOR)
if(NOT ANDROID_TEMPORARY_FILES_LOCATION)
- set(ANDROID_TEMPORARY_FILES_LOCATION "/cache" CACHE STRING "The path on the Android device that should be used for temporary files")
+ set(ANDROID_TEMPORARY_FILES_LOCATION "/data/local/cache" CACHE STRING "The path on the Android device that should be used for temporary files")
endif()
if(NOT ANDROID_SDK_ROOT)
if(CMAKE_HOST_SYSTEM MATCHES "Windows.*")
set(ANDROID_SDK_ROOT "/opt/android-sdk" CACHE PATH "Location of the Android SDK")
endif()
endif()
- find_program(ANDROID_EMULATOR_PROGRAM emulator PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
+ find_program(ANDROID_EMULATOR_PROGRAM emulator PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES emulator NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
if(CMAKE_HOST_SYSTEM MATCHES "Windows.*")
- find_program(ANDROID_ANDROID_PROGRAM android.bat PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
+ find_program(ANDROID_AVDMANAGER_PROGRAM avdmanager PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
else()
- find_program(ANDROID_ANDROID_PROGRAM android PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
+ find_program(ANDROID_AVDMANAGER_PROGRAM avdmanager PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES cmdline-tools/latest/bin NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
endif()
find_program(ANDROID_ADB_PROGRAM adb PATHS ${ANDROID_SDK_ROOT} PATH_SUFFIXES platform-tools NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
- if(NOT ANDROID_EMULATOR_PROGRAM OR NOT ANDROID_ANDROID_PROGRAM OR NOT ANDROID_ADB_PROGRAM)
+ if(NOT ANDROID_EMULATOR_PROGRAM OR NOT ANDROID_AVDMANAGER_PROGRAM OR NOT ANDROID_ADB_PROGRAM)
message(FATAL_ERROR
"Failed to detect the Android SDK, please set ANDROID_SDK_ROOT to the location of your Android SDK"
"or set the missing tools manually!"
)
else()
- execute_process(COMMAND "${ANDROID_ANDROID_PROGRAM}" list avd RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_QUIET)
+ execute_process(COMMAND "${ANDROID_AVDMANAGER_PROGRAM}" list avd RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_QUIET)
string(REGEX MATCHALL "Name:[ \t]*[^\r\n]*" ANDROID_AVAILABLE_AVDS ${OUTPUT})
string(REGEX REPLACE "Name:[ \t]*([^\r\n;]*)" "\\1" ANDROID_AVAILABLE_AVDS "${ANDROID_AVAILABLE_AVDS}")
set(ANDROID_EMULATOR_AVD "${ANDROID_EMULATOR_AVD}" CACHE STRING "Android emulator Android Virtual Device (AVD) configuration" FORCE)
endfunction()
#
-# Generate a random ID that is hopefully unique
-# enough to be used as the instance UUID.
+# Generate the emulator name from the provided port.
+# Since the port decides the name of the emulator
+# anyway, this is just to check if the emulator really
+# exists under the expected name.
# VAR - the name of the variable that will receive
-# the generated UUID as a string value
+# the generated name as a string value
# Will ignore all additional arguments.
#
-function(DCMTK_ANDROID_EMULATOR_GENERATE_UUID VAR)
- string(RANDOM LENGTH 20 RAND)
- string(TIMESTAMP TM)
- set(${VAR} "${TM}${RAND}")
- string(MD5 ${VAR} ${${VAR}})
+function(DCMTK_ANDROID_EMULATOR_GENERATE_NAME_FROM_PORT VAR)
+ set(${VAR} "emulator-${ANDROID_EMULATOR_PORT}")
set(${VAR} ${${VAR}} PARENT_SCOPE)
endfunction()
#
-# Tries to query the UUID property of an accessible Android device.
+# Tries to query the emulator name of an accessible Android device.
# EMULATOR_NAME - the device name, as returned by DCMTK_ANDROID_LIST_EMULATORS
-# VAR - the name of the variable that will be set to the device UUID
+# VAR - the name of the variable that will be set to the emulator name
# Will unset the variable referred to by VAR if no device with the given name
# is accessible or the device is offline.
# Will ignore all additional arguments.
#
-function(DCMTK_ANDROID_GET_EMULATOR_UUID EMULATOR_NAME VAR)
- execute_process(
- COMMAND "${ANDROID_ADB_PROGRAM}" -s "${EMULATOR_NAME}" shell getprop "ro.emu.uuid"
- RESULT_VARIABLE RESULT
- OUTPUT_VARIABLE OUTPUT
- ERROR_QUIET
- )
+function(DCMTK_ANDROID_GET_EMULATOR_NAME_FROM_PORT EMULATOR_NAME VAR)
DCMTK_UNSET_PARENT_SCOPE(${VAR})
- if(NOT RESULT)
- string(STRIP "${OUTPUT}" UUID)
- if(UUID)
- set("${VAR}" ${UUID} PARENT_SCOPE)
- endif()
+ if(ANDROID_EMULATOR_PORT)
+ set(EMULATOR_NAME "emulator-${ANDROID_EMULATOR_PORT}" PARENT_SCOPE)
endif()
endfunction()
#
# Retrieves the name of the emulator instance referred to by
-# the given UUID. Will wait until the device becomes online
+# the given port. Will wait until the device becomes online
# to query the name.
# VAR - the name of the variable that will be set
# to the device name
-# EMULATOR_UUID - the emulator UUID of the device to inquired
+# EMULATOR_NAME_FROM_PORT - the emulator name of the device to inquired
# Will wait until all available devices are online or the right
# one has been found.
# Will ignore all additional arguments.
#
-function(DCMTK_ANDROID_GET_EMULATOR_NAME VAR EMULATOR_UUID)
+function(DCMTK_ANDROID_GET_EMULATOR_NAME VAR EMULATOR_NAME_FROM_PORT)
DCMTK_ANDROID_LIST_EMULATORS(ONLINE_EMULATORS OFFLINE_EMULATORS)
foreach(EMULATOR ${ONLINE_EMULATORS})
- DCMTK_ANDROID_GET_EMULATOR_UUID("${EMULATOR}" UUID)
- if(EMULATOR_UUID STREQUAL UUID)
+ DCMTK_ANDROID_GET_EMULATOR_NAME_FROM_PORT("${EMULATOR}" ANDROID_EMULATOR_PORT)
+ # The emulator could have a different name in another language, but the port should always
+ # be the same.
+ if(EMULATOR_NAME MATCHES ".*-${ANDROID_EMULATOR_PORT}")
set("${VAR}" "${EMULATOR}" PARENT_SCOPE)
return()
endif()
ERROR_QUIET
)
if(NOT RESULT)
- DCMTK_ANDROID_GET_EMULATOR_UUID("${EMULATOR}" UUID)
- if(UUID)
- if(EMULATOR_UUID STREQUAL UUID)
+ if(ANDROID_EMULATOR_PORT)
+ if(EMULATOR_NAME STREQUAL "emulator-${ANDROID_EMULATOR_PORT}")
set("${VAR}" "${EMULATOR}" PARENT_SCOPE)
return()
endif()
#
function(DCMTK_ANDROID_START_EMULATOR VAR)
DCMTK_SETUP_ANDROID_EMULATOR()
+ if(NOT ANDROID_EMULATOR_PORT)
+ message(FATAL_ERROR "Please provide the port the Android emulator should use. The range is 5554 to 5682 and the port should be an even number.")
+ else()
+ set(ANDROID_EMULATOR_PORT ${ANDROID_EMULATOR_PORT} CACHE INTERNAL "")
+ endif()
if(NOT ANDROID_EMULATOR_AVD)
message(FATAL_ERROR "Please select which Android emulator Android Virtual Device (AVD) configuration to use!")
else()
DCMTK_ANDROID_GET_OBJECT_PROPERTIES("${VAR}")
if(NOT EMULATOR_STATE)
- DCMTK_ANDROID_EMULATOR_GENERATE_UUID(EMULATOR_UUID)
+ DCMTK_ANDROID_EMULATOR_GENERATE_NAME_FROM_PORT(EMULATOR_NAME_FROM_PORT)
elseif(EMULATOR_STATE STREQUAL "RUNNING")
- DCMTK_ANDROID_GET_EMULATOR_UUID("${EMULATOR_NAME}" UUID)
+ DCMTK_ANDROID_GET_EMULATOR_NAME_FROM_PORT("${EMULATOR_NAME}" EMULATOR_NAME_FROM_PORT)
# Do nothing if the running emulator instance is ok and can be reused.
# Otherwise restart it.
- if(UUID STREQUAL EMULATOR_UUID)
+ if(EMULATOR_NAME_FROM_PORT STREQUAL EMULATOR_NAME)
message(STATUS "Reusing already running Android device emulator...")
return()
endif()
elseif(EMULATOR_STATE STREQUAL "STARTING")
# Is it really starting, or has somebody aborted it?
message(STATUS "Found previously started Android device emulator, checking if it's still present...")
- DCMTK_ANDROID_GET_EMULATOR_NAME(EMULATOR_NAME "${EMULATOR_UUID}")
+ DCMTK_ANDROID_GET_EMULATOR_NAME(EMULATOR_NAME "${EMULATOR_NAME_FROM_PORT}")
if(EMULATOR_NAME)
message(STATUS "Found previously started Android device emulator, checking if it's still present... yes")
- DCMTK_ANDROID_SET_OBJECT_PROPERTIES(${VAR} RUNNING "${EMULATOR_UUID}" "${EMULATOR_NAME}")
+ DCMTK_ANDROID_SET_OBJECT_PROPERTIES(${VAR} RUNNING "${EMULATOR_NAME}")
return()
endif()
message(STATUS "Found previously started Android device emulator, checking if it's still present... no")
endif()
message(STATUS "Starting the Android device emulator...")
if(CMAKE_HOST_SYSTEM MATCHES "Windows.*")
- set(COMMAND sh -c "${ANDROID_EMULATOR_PROGRAM} -avd ${ANDROID_EMULATOR_AVD} -no-boot-anim -prop ro.emu.uuid=${EMULATOR_UUID} >${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android-emulator.log 2>&1 < /dev/null &")
+ set(COMMAND sh -c "${ANDROID_EMULATOR_PROGRAM} -avd ${ANDROID_EMULATOR_AVD} -no-boot-anim -port ${ANDROID_EMULATOR_PORT} >${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android-emulator.log 2>&1 < /dev/null &")
else()
- set(COMMAND sh -c "${ANDROID_EMULATOR_PROGRAM} -avd ${ANDROID_EMULATOR_AVD} -no-window -no-boot-anim -prop ro.emu.uuid=${EMULATOR_UUID} >${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android-emulator.log 2>&1 < /dev/null &")
+ set(COMMAND sh -c "${ANDROID_EMULATOR_PROGRAM} -avd ${ANDROID_EMULATOR_AVD} -no-window -no-boot-anim -port ${ANDROID_EMULATOR_PORT} >${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android-emulator.log 2>&1 < /dev/null &")
endif()
execute_process(
COMMAND ${COMMAND}
ERROR_QUIET
)
if(NOT RESULT)
- DCMTK_ANDROID_SET_OBJECT_PROPERTIES("${VAR}" STARTING "${EMULATOR_UUID}" "")
+ DCMTK_ANDROID_SET_OBJECT_PROPERTIES("${VAR}" STARTING "${EMULATOR_NAME}")
else()
DCMTK_ANDROID_DESTROY_OBJECT("${VAR}")
message(FATAL_ERROR "Error starting Android emulator.")
# Restart adb/the emulated device in root mode so that we gain write access to
# the device.
# Newer versions of the SDK seem to require this for doing anything meaningful
-# with it.
+# with it. It also only works on emulated devices without Playstore API.
# EMULATOR_NAME - the name of the emulated device that shall be rooted.
# Will ignore all additional arguments.
#
OUTPUT_QUIET
ERROR_QUIET
)
- # the SDK was seemingly designed by a five year old, the device will
- # become invisible while it is being rooted, therefore, wait until
- # it is ready again
+ # The device will become invisible while it is being rooted, therefore,
+ # wait until it is ready again.
set(STATUS 1)
while(STATUS)
execute_process(
else()
message(STATUS "Waiting until the Android device emulator is ready to receive instructions...")
while(NOT EMULATOR_NAME)
- DCMTK_ANDROID_GET_EMULATOR_NAME(EMULATOR_NAME "${EMULATOR_UUID}")
+ DCMTK_ANDROID_GET_EMULATOR_NAME(EMULATOR_NAME "${EMULATOR_NAME_FROM_PORT}")
endwhile()
DCMTK_ANDROID_ADB_ROOT("${EMULATOR_NAME}")
- DCMTK_ANDROID_SET_OBJECT_PROPERTIES("${VAR}" RUNNING "${EMULATOR_UUID}" "${EMULATOR_NAME}")
+ DCMTK_ANDROID_SET_OBJECT_PROPERTIES("${VAR}" RUNNING "${EMULATOR_NAME}")
endif()
endfunction()
ERROR_QUIET
)
if(NOT RESULT)
- DCMTK_ANDROID_SET_OBJECT_PROPERTIES("${VAR}" STOPPED "${EMULATOR_UUID}" "")
+ DCMTK_ANDROID_SET_OBJECT_PROPERTIES("${VAR}" STOPPED "${EMULATOR_NAME}")
else()
message(WARNING "Unable to stop the android device emulator, please shutdown \"${EMULATOR_NAME}\" manually!")
endif()
/* Define the environment variable path separator */
#define ENVIRONMENT_PATH_SEPARATOR '@ENVIRONMENT_PATH_SEPARATOR@'
-/* Define to 1 if you have the `access' function. */
-#cmakedefine HAVE_ACCESS @HAVE_ACCESS@
-
/* Define to 1 if you have the <alloca.h> header file. */
#cmakedefine HAVE_ALLOCA_H @HAVE_ALLOCA_H@
/* Define to 1 if you have the <arpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H @HAVE_ARPA_INET_H@
-/* Define to 1 if you have the `bcmp' function. */
-#cmakedefine HAVE_BCMP @HAVE_BCMP@
+/* Define to 1 if you have the <cstdint> header file. */
+#cmakedefine HAVE_CSTDINT @HAVE_CSTDINT@
/* Define to 1 if you have the `cuserid' function. */
#cmakedefine HAVE_CUSERID @HAVE_CUSERID@
/* Define to 1 if you have the `fgetln' function. */
#cmakedefine HAVE_FGETLN @HAVE_FGETLN@
-/* Define if your system has a declaration for fp_except_t in ieeefp.h */
-#cmakedefine HAVE_DECLARATION_FP_EXCEPT_T @HAVE_DECLARATION_FP_EXCEPT_T@
-
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.*/
#cmakedefine HAVE_DIRENT_H @HAVE_DIRENT_H@
/* Define to 1 if <errno.h> defined ENAMETOOLONG. */
#cmakedefine HAVE_ENAMETOOLONG @HAVE_ENAMETOOLONG@
-/* Define to 1 if you have the <fcntl.h> header file. */
-#cmakedefine HAVE_FCNTL_H @HAVE_FCNTL_H@
-
-/* Define to 1 if you have the `finite' function. */
-#cmakedefine HAVE_FINITE @HAVE_FINITE@
-
/* Define to 1 if you have the `flock' function. */
#cmakedefine HAVE_FLOCK @HAVE_FLOCK@
/* Define to 1 if you have the `getlogin_r' function. */
#cmakedefine HAVE_GETLOGIN_R @HAVE_GETLOGIN_R@
-/* Define to 1 if you have the `getpid' function. */
-#cmakedefine HAVE_GETPID @HAVE_GETPID@
-
/* Define to 1 if you have the `getpwnam' function. */
#cmakedefine HAVE_GETPWNAM @HAVE_GETPWNAM@
-/* Define to 1 if you have the `getrusage' function. */
-#cmakedefine HAVE_GETRUSAGE @HAVE_GETRUSAGE@
-
/* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY @HAVE_GETTIMEOFDAY@
/* Define to 1 if you have the <ieeefp.h> header file. */
#cmakedefine HAVE_IEEEFP_H @HAVE_IEEEFP_H@
-/* Define to 1 if you have the `index' function. */
-#cmakedefine HAVE_INDEX @HAVE_INDEX@
-
-/* Define if your system declares argument 3 of accept() as int * instead of
- size_t * or socklen_t * */
-#cmakedefine HAVE_INTP_ACCEPT @HAVE_INTP_ACCEPT@
-
-/* Define if your system declares argument 5 of getsockopt() as int * instead
- of size_t * or socklen_t */
-#cmakedefine HAVE_INTP_GETSOCKOPT @HAVE_INTP_GETSOCKOPT@
-
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H @HAVE_IO_H@
-/* Define to 1 if you have the `itoa' function. */
-#cmakedefine HAVE_ITOA @HAVE_ITOA@
-
/* Define to 1 if you have the <langinfo.h> header file. */
#cmakedefine HAVE_LANGINFO_H @HAVE_LANGINFO_H@
/* Define to 1 if you have the <libc.h> header file. */
#cmakedefine HAVE_LIBC_H @HAVE_LIBC_H@
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-#cmakedefine HAVE_LIBNSL @HAVE_LIBNSL@
-
/* Define to 1 if the <libpng/png.h> header shall be used instead of <png.h>. */
#cmakedefine HAVE_LIBPNG_PNG_H @HAVE_LIBPNG_PNG_H@
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#cmakedefine HAVE_LIBSOCKET @HAVE_LIBSOCKET@
-
-/* Define to 1 if you have the `listen' function. */
-#cmakedefine HAVE_LISTEN @HAVE_LISTEN@
-
/* Define to 1 if you have the `localtime_r' function. */
#cmakedefine HAVE_LOCALTIME_R @HAVE_LOCALTIME_R@
/* Define to 1 if you have the `malloc_debug' function. */
#cmakedefine HAVE_MALLOC_DEBUG @HAVE_MALLOC_DEBUG@
-/* Define to 1 if you have the <malloc.h> header file. */
-#cmakedefine HAVE_MALLOC_H @HAVE_MALLOC_H@
-
/* Define to 1 if you have the `mkstemp' function. */
#cmakedefine HAVE_MKSTEMP @HAVE_MKSTEMP@
-/* Define to 1 if you have the `mktemp' function. */
-#cmakedefine HAVE_MKTEMP @HAVE_MKTEMP@
-
/* Define to 1 if you have the <mqueue.h> header file. */
#cmakedefine HAVE_MQUEUE_H @HAVE_MQUEUE_H@
/* Define to 1 if you have readdir_r */
#cmakedefine HAVE_READDIR_R @HAVE_READDIR_R@
-/* Define if your system has a prototype for feenableexcept in fenv.h */
-#cmakedefine HAVE_PROTOTYPE_FEENABLEEXCEPT @HAVE_PROTOTYPE_FEENABLEEXCEPT@
-
-/* Define if your system has a prototype for finite in math.h */
-#cmakedefine HAVE_PROTOTYPE_FINITE @HAVE_PROTOTYPE_FINITE@
-
/* Define to 1 if your has a prototype for `TryAcquireSRWLockShared' in windows.h (Win32 only). */
#cmakedefine HAVE_PROTOTYPE_TRYACQUIRESRWLOCKSHARED @HAVE_PROTOTYPE_TRYACQUIRESRWLOCKSHARED@
unistd.h */
#cmakedefine HAVE_PROTOTYPE_GETTIMEOFDAY @HAVE_PROTOTYPE_GETTIMEOFDAY@
-/* Define if your system has a prototype for std::isinf in cmath */
-#cmakedefine HAVE_PROTOTYPE_STD__ISINF @HAVE_PROTOTYPE_STD__ISINF@
-
-/* Define if your system has a prototype for std::isnan in cmath */
-#cmakedefine HAVE_PROTOTYPE_STD__ISNAN @HAVE_PROTOTYPE_STD__ISNAN@
-
-/* Define if your system has a prototype for fpclassf in math.h */
-#cmakedefine HAVE_PROTOTYPE__FPCLASSF @HAVE_PROTOTYPE__FPCLASSF@
-
-/* Define if your system has a prototype for mkstemp in libc.h unistd.h
- stdlib.h */
-#cmakedefine HAVE_PROTOTYPE_MKSTEMP @HAVE_PROTOTYPE_MKSTEMP@
-
-/* Define if your system has a prototype for mktemp in libc.h unistd.h
- stdlib.h */
-#cmakedefine HAVE_PROTOTYPE_MKTEMP @HAVE_PROTOTYPE_MKTEMP@
-
-/* Define if your system has a prototype for std::vfprintf in stdarg.h */
-#cmakedefine HAVE_PROTOTYPE_STD__VFPRINTF @HAVE_PROTOTYPE_STD__VFPRINTF@
-
/* Define if your system has a prototype for std::vsnprintf in stdio.h */
#cmakedefine HAVE_PROTOTYPE_STD__VSNPRINTF @HAVE_PROTOTYPE_STD__VSNPRINTF@
/* Define if your system has a prototype for _stricmp in string.h */
#cmakedefine HAVE_PROTOTYPE__STRICMP @HAVE_PROTOTYPE__STRICMP@
-/* Define if your system has a prototype for nanosleep in time.h */
-#cmakedefine HAVE_PROTOTYPE_NANOSLEEP @HAVE_PROTOTYPE_NANOSLEEP@
-
/* Define to 1 if you have the <pthread.h> header file. */
#cmakedefine HAVE_PTHREAD_H @HAVE_PTHREAD_H@
/* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H @HAVE_PWD_H@
-/* Define to 1 if you have the `rindex' function. */
-#cmakedefine HAVE_RINDEX @HAVE_RINDEX@
-
/* Define to 1 if you have the <semaphore.h> header file. */
#cmakedefine HAVE_SEMAPHORE_H @HAVE_SEMAPHORE_H@
/* Define to 1 if you have the `sleep' function. */
#cmakedefine HAVE_SLEEP @HAVE_SLEEP@
-/* Define to 1 if you have the `stat' function. */
-#cmakedefine HAVE_STAT @HAVE_STAT@
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@
-
-/* Define to 1 if you have the C++11 <system_error> header file. */
-#cmakedefine HAVE_SYSTEM_ERROR @HAVE_SYSTEM_ERROR@
-
-/* Define to 1 if you have the <cstdint> header file. */
-#cmakedefine HAVE_CSTDINT @HAVE_CSTDINT@
-
-/* Define to 1 if you have the `strdup' function. */
-#cmakedefine HAVE_STRDUP @HAVE_STRDUP@
-
/* Define to 1 if `strerror_r' returns a char*. */
#cmakedefine HAVE_CHARP_STRERROR_R @HAVE_CHARP_STRERROR_R@
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.*/
#cmakedefine HAVE_SYS_DIR_H @HAVE_SYS_DIR_H@
-/* Define to 1 if you have the <sys/errno.h> header file. */
-#cmakedefine HAVE_SYS_ERRNO_H @HAVE_SYS_ERRNO_H@
-
/* Define to 1 if you have the <sys/file.h> header file. */
#cmakedefine HAVE_SYS_FILE_H @HAVE_SYS_FILE_H@
/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H @HAVE_SYS_SOCKET_H@
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@
-
/* Define to 1 if you have the <sys/syscall.h> header file. */
#cmakedefine HAVE_SYS_SYSCALL_H @HAVE_SYS_SYSCALL_H@
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H @HAVE_SYS_TIME_H@
-/* Define to 1 if you have the <sys/types.h> header file. */
-#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@
-
/* Define to 1 if you have the <sys/un.h> header file. */
#cmakedefine HAVE_SYS_UN_H @HAVE_SYS_UN_H@
/* Define to 1 if you have the <thread.h> header file. */
#cmakedefine HAVE_THREAD_H @HAVE_THREAD_H@
-/* Define to 1 if you have the C++11 <tuple> header file. */
-#cmakedefine HAVE_TUPLE @HAVE_TUPLE@
-
/* Define to 1 if you have the C++11 <type_traits> header file. */
#cmakedefine HAVE_TYPE_TRAITS @HAVE_TYPE_TRAITS@
/* Define to 1 if you have the `vfprintf_s' function. */
#cmakedefine HAVE_VFPRINTF_S @HAVE_VFPRINTF_S@
-/* Define to 1 if you have the `vsnprintf' function. */
-#cmakedefine HAVE_VSNPRINTF @HAVE_VSNPRINTF@
-
/* Define to 1 if you have the `vsprintf_s' function. */
#cmakedefine HAVE_VSPRINTF_S @HAVE_VSPRINTF_S@
/* Select LFS mode (defined above) that shall be used or don't define it */
#cmakedefine DCMTK_ENABLE_LFS @DCMTK_LFS_MODE@
-/* The size of a `double', as computed by sizeof. */
-#cmakedefine SIZEOF_DOUBLE @SIZEOF_DOUBLE@
-
-/* The size of a `float', as computed by sizeof. */
-#cmakedefine SIZEOF_FLOAT @SIZEOF_FLOAT@
-
/* The size of a `int', as computed by sizeof. */
#cmakedefine SIZEOF_INT @SIZEOF_INT@
/* The size of a `long', as computed by sizeof. */
#cmakedefine SIZEOF_LONG @SIZEOF_LONG@
-/* The size of a `short', as computed by sizeof. */
-#cmakedefine SIZEOF_SHORT @SIZEOF_SHORT@
-
/* The size of a `void *', as computed by sizeof. */
#cmakedefine SIZEOF_VOID_P @SIZEOF_VOID_P@
#endif
#endif
-/* Set typedefs as needed for JasPer library */
-#cmakedefine HAVE_UCHAR_TYPEDEF
-#ifndef HAVE_UCHAR_TYPEDEF
-typedef unsigned char uchar;
-#endif
-
-#cmakedefine HAVE_USHORT_TYPEDEF
-#ifndef HAVE_USHORT_TYPEDEF
-typedef unsigned short ushort;
-#endif
-
-#cmakedefine HAVE_UINT_TYPEDEF
-#ifndef HAVE_UINT_TYPEDEF
-typedef unsigned int uint;
-#endif
-
-#cmakedefine HAVE_ULONG_TYPEDEF
-#ifndef HAVE_ULONG_TYPEDEF
-typedef unsigned long ulong;
-#endif
-
#cmakedefine HAVE_LONG_LONG
#cmakedefine HAVE_UNSIGNED_LONG_LONG
#cmakedefine HAVE_UINT64_T @HAVE_UINT64_T@
/* Additional settings for Borland C++ Builder */
-#ifdef __BORLANDC__
+
+#if defined(__BORLANDC__) && (!defined(_WIN64) || !defined(__MINGW64__))
+#define HAVE_CLASSIC_BORLAND_COMPILER
+#endif
+
+#ifdef HAVE_CLASSIC_BORLAND_COMPILER
+#define _MSC_VER 1200 /* Treat Borland C++ 5.5 as MSVC6. */
#define _stricmp stricmp /* _stricmp in MSVC is stricmp in Borland C++ */
#define _strnicmp strnicmp /* _strnicmp in MSVC is strnicmp in Borland C++ */
- #pragma warn -8027 /* disable Warning W8027 "functions containing while are not expanded inline" */
- #pragma warn -8004 /* disable Warning W8004 "variable is assigned a value that is never used" */
- #pragma warn -8012 /* disable Warning W8012 "comparing signed and unsigned values" */
+#pragma warn -8027 /* disable Warning W8027 "functions containing while are not expanded inline" */
+#pragma warn -8004 /* disable Warning W8004 "variable is assigned a value that is never used" */
+#pragma warn -8012 /* disable Warning W8012 "comparing signed and unsigned values" */
#ifdef WITH_THREADS
#define __MT__ /* required for _beginthreadex() API in <process.h> */
#define _MT /* required for _errno on BCB6 */
#endif
-#define HAVE_PROTOTYPE_MKTEMP 1
-#undef HAVE_SYS_UTIME_H
-#define _MSC_VER 1200 /* Treat Borland C++ 5.5 as MSVC6. */
-#endif /* __BORLANDC__ */
-
-/* Platform specific settings for Visual C++
- * By default, enable ANSI standard C++ includes on Visual C++ 6 and newer
- * _MSC_VER == 1100 on Microsoft Visual C++ 5.0
- * _MSC_VER == 1200 on Microsoft Visual C++ 6.0
- * _MSC_VER == 1300 on Microsoft Visual C++ 7.0
- * _MSC_VER == 1310 on Microsoft Visual C++ 7.1
- * _MSC_VER == 1400 on Microsoft Visual C++ 8.0
- */
+#endif /* HAVE_CLASSIC_BORLAND_COMPILER */
-#ifdef _MSC_VER
-#if _MSC_VER <= 1200 /* Additional settings for VC6 and older */
-/* disable warning that return type for 'identifier::operator ->' is not a UDT or reference to a UDT */
- #pragma warning( disable : 4284 )
-#define HAVE_OLD_INTERLOCKEDCOMPAREEXCHANGE 1
-#else
-#define HAVE_VSNPRINTF 1
-#endif /* _MSC_VER <= 1200 */
+/* Platform specific settings for Visual C++ */
+#ifdef _MSC_VER
#pragma warning( disable : 4251 ) /* disable warnings about needed dll-interface */
/* http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html */
#pragma warning( disable : 4099 ) /* disable warning about mismatched class and struct keywords */
/* http://alfps.wordpress.com/2010/06/22/cppx-is-c4099-really-a-sillywarning-disabling-msvc-sillywarnings */
#pragma warning( disable : 4521 ) /* disable warnings about multiple copy constructors and assignment operators,*/
#pragma warning( disable : 4522 ) /* since these are sometimes necessary for correct overload resolution*/
-
-#if _MSC_VER >= 1400 /* Additional settings for Visual Studio 2005 and newer */
#pragma warning( disable : 4996 ) /* disable warnings about "deprecated" C runtime functions */
#if _MSC_VER < 1900 /* Warning only available before Visual Studio 2015 */
#pragma warning( disable : 4351 ) /* disable warnings about "new behavior" when initializing the elements of an array */
#endif /* _MSC_VER < 1900 */
-#endif /* _MSC_VER >= 1400 */
#endif /* _MSC_VER */
-/* Define if ANSI standard C++ includes use std namespace */
-#cmakedefine HAVE_STD_NAMESPACE @HAVE_STD_NAMESPACE@
-
-/* Define if the compiler supports std::nothrow */
-#cmakedefine HAVE_STD__NOTHROW @HAVE_STD__NOTHROW@
-
-/* Define if the compiler supports operator delete (std::nothrow) */
-#cmakedefine HAVE_NOTHROW_DELETE @HAVE_NOTHROW_DELETE@
-
/* Define if the compiler supports static_assert */
#cmakedefine HAVE_STATIC_ASSERT @HAVE_STATIC_ASSERT@
/* Define if the compiler supports __declspec(deprecated("message")) */
#cmakedefine HAVE_DECLSPEC_DEPRECATED_MSG @HAVE_DECLSPEC_DEPRECATED_MSG@
-/* Define if your system has a prototype for std::vfprintf in stdarg.h */
-#cmakedefine HAVE_PROTOTYPE_STD__VFPRINTF @HAVE_PROTOTYPE_STD__VFPRINTF@
-
/* Define if your system has off64_t */
#cmakedefine HAVE_OFF64_T @HAVE_OFF64_T@
/* Define if your system uses _pclose instead of pclose */
#cmakedefine HAVE_PCLOSE @HAVE_PCLOSE@
-/* Define if your system provides sigjmp_buf as conditional jmp_buf alternative */
-#cmakedefine HAVE_SIGJMP_BUF @HAVE_SIGJMP_BUF@
-
/* Define if we can use C++11 */
#cmakedefine HAVE_CXX11 @HAVE_CXX11@
-#if defined(HAVE_CXX11) && defined(__cplusplus) && __cplusplus < 201103L
+#if defined(HAVE_CXX11)
+# if defined(_MSVC_LANG)
+# if _MSVC_LANG < 201103L
+#error \
+DCMTK was configured to use C++11 features, but your compiler does not or was not configured to provide them.
+# endif
+# elif defined(__cplusplus)
+# if __cplusplus < 201103L
#error \
DCMTK was configured to use C++11 features, but your compiler does not or was not configured to provide them.
+# endif
+# endif
#endif
/* Define if we can use C++14 */
#cmakedefine HAVE_CXX14 @HAVE_CXX14@
-#if defined(HAVE_CXX14) && defined(__cplusplus) && __cplusplus < 201402L
+#if defined(HAVE_CXX14)
+# if defined(_MSVC_LANG)
+# if _MSVC_LANG < 201402L
#error \
DCMTK was configured to use C++14 features, but your compiler does not or was not configured to provide them.
+# endif
+# elif defined(__cplusplus)
+# if __cplusplus < 201402L
+#error \
+DCMTK was configured to use C++14 features, but your compiler does not or was not configured to provide them.
+# endif
+# endif
#endif
/* Define if we can use C++17 */
#cmakedefine HAVE_CXX17 @HAVE_CXX17@
-#if defined(HAVE_CXX17) && defined(__cplusplus) && __cplusplus < 201703L
+#if defined(HAVE_CXX17)
+# if defined(_MSVC_LANG)
+# if _MSVC_LANG < 201703L
#error \
DCMTK was configured to use C++17 features, but your compiler does not or was not configured to provide them.
+# endif
+# elif defined(__cplusplus)
+# if __cplusplus < 201703L
+#error \
+DCMTK was configured to use C++17 features, but your compiler does not or was not configured to provide them.
+# endif
+# endif
#endif
+
/* Define if we can use C++20 */
#cmakedefine HAVE_CXX20 @HAVE_CXX20@
-#if defined(HAVE_CXX20) && defined(__cplusplus) && __cplusplus < 202002L
+#if defined(HAVE_CXX20)
+# if defined(_MSVC_LANG)
+# if _MSVC_LANG < 202002L
#error \
DCMTK was configured to use C++20 features, but your compiler does not or was not configured to provide them.
+# endif
+# elif defined(__cplusplus)
+# if __cplusplus < 202002L
+#error \
+DCMTK was configured to use C++20 features, but your compiler does not or was not configured to provide them.
+# endif
+# endif
#endif
/* Define if the compiler supports __alignof__ */
/* Define if we are supposed to use STL's atomic */
#cmakedefine HAVE_STL_ATOMIC @HAVE_STL_ATOMIC@
-/* Define if the input iterator category is supported */
-#cmakedefine HAVE_CONTIGUOUS_ITERATOR_CATEGORY @HAVE_CONTIGUOUS_ITERATOR_CATEGORY@
-
/* Feature Tests for the OpenSSL Library */
/* Define if your OpenSSL library provides the RAND_egd function */
/* Define if we have the <openssl/provider.h> header file*/
#cmakedefine HAVE_OPENSSL_PROVIDER_H @HAVE_OPENSSL_PROVIDER_H@
-
/* Historical C/C++ language features and APIs that are guaranteed by C++98,
- * C89, or POSIX.1-2001 for Posix platforms, and thus not tested anymore.
+ * C99, or POSIX.1-2001 for Posix platforms, or are not used anywhere in DCMTK,
+ * and thus not tested anymore.
* These macros are deprecated and will be removed from a future version.
*/
-
#if defined(POISON_DEPRECATED_FEATURE_MACROS) && defined(__GNUC__)
+#pragma GCC poison HAVE_ACCESS
#pragma GCC poison HAVE_ASSERT_H
#pragma GCC poison HAVE_BIDIRECTIONAL_ITERATOR_CATEGORY
#pragma GCC poison HAVE_CLASS_TEMPLATE
#pragma GCC poison HAVE_DYNAMIC_CAST
#pragma GCC poison HAVE_ERRNO_H
#pragma GCC poison HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION
+#pragma GCC poison HAVE_FCNTL_H
#pragma GCC poison HAVE_FENV_H
#pragma GCC poison HAVE_FLOAT_H
#pragma GCC poison HAVE_FORWARD_ITERATOR_CATEGORY
#pragma GCC poison HAVE_FSTREAM
#pragma GCC poison HAVE_FUNCTION_TEMPLATE
#pragma GCC poison HAVE_GETENV
+#pragma GCC poison HAVE_GETPID
#pragma GCC poison HAVE_INPUT_ITERATOR_CATEGORY
#pragma GCC poison HAVE_INTTYPES_H
#pragma GCC poison HAVE_IOMANIP
#pragma GCC poison HAVE_MEMCPY
#pragma GCC poison HAVE_MEMMOVE
#pragma GCC poison HAVE_MEMSET
+#pragma GCC poison HAVE_MKTEMP
+#pragma GCC poison HAVE_NOTHROW_DELETE
#pragma GCC poison HAVE_OUTPUT_ITERATOR_CATEGORY
#pragma GCC poison HAVE_PROTOTYPE_ISINF
#pragma GCC poison HAVE_PROTOTYPE_ISNAN
+#pragma GCC poison HAVE_PROTOTYPE_MKTEMP
+#pragma GCC poison HAVE_PROTOTYPE_STD__ISINF
+#pragma GCC poison HAVE_PROTOTYPE_STD__ISNAN
+#pragma GCC poison HAVE_PROTOTYPE_STD__VFPRINTF
+#pragma GCC poison HAVE_PROTOTYPE_VSNPRINTF
#pragma GCC poison HAVE_RANDOM_ACCESS_ITERATOR_CATEGORY
#pragma GCC poison HAVE_REINTERPRET_CAST
#pragma GCC poison HAVE_SETJMP_H
#pragma GCC poison HAVE_SIGNAL_H
#pragma GCC poison HAVE_SSTREAM
+#pragma GCC poison HAVE_STAT
#pragma GCC poison HAVE_STATIC_CAST
#pragma GCC poison HAVE_STATIC_TEMPLATE_METHOD
#pragma GCC poison HAVE_STDARG_H
#pragma GCC poison HAVE_STDBOOL_H
#pragma GCC poison HAVE_STDDEF_H
+#pragma GCC poison HAVE_STDINT_H
#pragma GCC poison HAVE_STDIO_H
#pragma GCC poison HAVE_STDLIB_H
+#pragma GCC poison HAVE_STD_NAMESPACE
+#pragma GCC poison HAVE_STD__NOTHROW
#pragma GCC poison HAVE_STRCHR
+#pragma GCC poison HAVE_STRDUP
#pragma GCC poison HAVE_STRERROR
#pragma GCC poison HAVE_STRING_H
#pragma GCC poison HAVE_STRSTR
#pragma GCC poison HAVE_STRSTREAM
#pragma GCC poison HAVE_STRTOUL
+#pragma GCC poison HAVE_SYS_STAT_H
+/* #pragma GCC poison HAVE_SYS_TYPES_H */ /* this macro is used in some Linux system header files. */
#pragma GCC poison HAVE_TEMPNAM
#pragma GCC poison HAVE_TIME_H
#pragma GCC poison HAVE_TMPNAM
#pragma GCC poison HAVE_TYPENAME
#pragma GCC poison HAVE_VPRINTF
+#pragma GCC poison HAVE_VSNPRINTF
#pragma GCC poison HAVE_WCHAR_H
#pragma GCC poison HAVE_WCSTOMBS
#pragma GCC poison HAVE_WCTYPE_H
#pragma GCC poison SIZEOF_CHAR
+#pragma GCC poison SIZEOF_DOUBLE
+#pragma GCC poison SIZEOF_FLOAT
+#pragma GCC poison SIZEOF_SHORT
#pragma GCC poison STDC_HEADERS
#endif
#if !defined(POISON_DEPRECATED_FEATURE_MACROS) || !defined(__GNUC__)
+#define HAVE_ACCESS 1
#define HAVE_ASSERT_H 1
#define HAVE_BIDIRECTIONAL_ITERATOR_CATEGORY 1
#define HAVE_CLASS_TEMPLATE 1
#define HAVE_DYNAMIC_CAST 1
#define HAVE_ERRNO_H 1
#define HAVE_EXPLICIT_TEMPLATE_SPECIALIZATION 1
+#define HAVE_FCNTL_H 1
#define HAVE_FENV_H 1
#define HAVE_FLOAT_H 1
#define HAVE_FORWARD_ITERATOR_CATEGORY 1
#define HAVE_FSTREAM 1
#define HAVE_FUNCTION_TEMPLATE 1
#define HAVE_GETENV 1
+#define HAVE_GETPID 1
#define HAVE_INPUT_ITERATOR_CATEGORY 1
#define HAVE_INTTYPES_H 1
#define HAVE_IOMANIP 1
#define HAVE_MEMCPY 1
#define HAVE_MEMMOVE 1
#define HAVE_MEMSET 1
+#define HAVE_MKTEMP 1
+#define HAVE_NOTHROW_DELETE 1
#define HAVE_OUTPUT_ITERATOR_CATEGORY 1
#define HAVE_PROTOTYPE_ISINF 1
#define HAVE_PROTOTYPE_ISNAN 1
+#define HAVE_PROTOTYPE_MKTEMP 1
+#define HAVE_PROTOTYPE_STD__ISINF 1
+#define HAVE_PROTOTYPE_STD__ISNAN 1
+#define HAVE_PROTOTYPE_STD__VFPRINTF 1
+#define HAVE_PROTOTYPE_VSNPRINTF 1
#define HAVE_RANDOM_ACCESS_ITERATOR_CATEGORY 1
#define HAVE_REINTERPRET_CAST 1
#define HAVE_SETJMP_H 1
#define HAVE_SIGNAL_H 1
#define HAVE_SSTREAM 1
+#define HAVE_STAT 1
#define HAVE_STATIC_CAST 1
#define HAVE_STATIC_TEMPLATE_METHOD 1
#define HAVE_STDARG_H 1
#define HAVE_STDBOOL_H 1
#define HAVE_STDDEF_H 1
+#define HAVE_STDINT_H 1
#define HAVE_STDIO_H 1
#define HAVE_STDLIB_H 1
+#define HAVE_STD_NAMESPACE 1
+#define HAVE_STD__NOTHROW 1
#define HAVE_STRCHR 1
+#define HAVE_STRDUP 1
#define HAVE_STRERROR 1
#define HAVE_STRING_H 1
#define HAVE_STRSTR 1
#define HAVE_STRSTREAM 1
#define HAVE_STRTOUL 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
#define HAVE_TEMPNAM 1
#define HAVE_TIME_H 1
#define HAVE_TMPNAM 1
#define HAVE_TYPENAME 1
#define HAVE_VPRINTF 1
+#define HAVE_VSNPRINTF 1
#define HAVE_WCHAR_H 1
#define HAVE_WCSTOMBS 1
#define HAVE_WCTYPE_H 1
#if defined(POISON_DEPRECATED_FEATURE_MACROS) && defined(__GNUC__)
#pragma GCC poison C_INLINE
+#pragma GCC poison HAVE_BCMP
#pragma GCC poison HAVE_BCOPY
+#pragma GCC poison HAVE_CONTIGUOUS_ITERATOR_CATEGORY
+#pragma GCC poison HAVE_DECLARATION_FP_EXCEPT_T
#pragma GCC poison HAVE_DECLARATION_STD__IOS_BASE__OPENMODE
#pragma GCC poison HAVE_DOPRNT
#pragma GCC poison HAVE_EMPTY_ARGC_ARGV
+#pragma GCC poison HAVE_FINITE
#pragma GCC poison HAVE_FSTREAM_H
+#pragma GCC poison HAVE_GETRUSAGE
+#pragma GCC poison HAVE_INDEX
+#pragma GCC poison HAVE_INTP_ACCEPT
+#pragma GCC poison HAVE_INTP_GETSOCKOPT
#pragma GCC poison HAVE_IOMANIP_H
#pragma GCC poison HAVE_IOSTREAM_H
#pragma GCC poison HAVE_IOS_NOCREATE
+#pragma GCC poison HAVE_ITOA
#pragma GCC poison HAVE_LIBIOSTREAM
+#pragma GCC poison HAVE_LIBNSL
+#pragma GCC poison HAVE_LIBSOCKET
+#pragma GCC poison HAVE_LISTEN
#pragma GCC poison HAVE_LONGLONG
+#pragma GCC poison HAVE_MALLOC_H
#pragma GCC poison HAVE_MEMORY_H
#pragma GCC poison HAVE_NDIR_H
#pragma GCC poison HAVE_NEW_H
#pragma GCC poison HAVE_OLD_READDIR_R
+#pragma GCC poison HAVE_PROTOTYPE_FINITE
+#pragma GCC poison HAVE_PROTOTYPE_MKSTEMP
+#pragma GCC poison HAVE_PROTOTYPE_NANOSLEEP
#pragma GCC poison HAVE_PROTOTYPE_STD__FINITE
#pragma GCC poison HAVE_PROTOTYPE_WAIT3
+#pragma GCC poison HAVE_PROTOTYPE_FEENABLEEXCEPT
+#pragma GCC poison HAVE_PROTOTYPE__FPCLASSF
+#pragma GCC poison HAVE_RINDEX
+#pragma GCC poison HAVE_SIGJMP_BUF
#pragma GCC poison HAVE_SSTREAM_H
#pragma GCC poison HAVE_STAT_H
#pragma GCC poison HAVE_STREAMBUF_H
#pragma GCC poison HAVE_STRSTREAM_H
#pragma GCC poison HAVE_STRSTREA_H
+#pragma GCC poison HAVE_SYSTEM_ERROR
+#pragma GCC poison HAVE_SYS_ERRNO_H
#pragma GCC poison HAVE_SYS_NDIR_H
+#pragma GCC poison HAVE_TUPLE
+#pragma GCC poison HAVE_UCHAR_TYPEDEF
+#pragma GCC poison HAVE_UINT_TYPEDEF
#pragma GCC poison HAVE_ULONGLONG
+#pragma GCC poison HAVE_ULONG_TYPEDEF
+#pragma GCC poison HAVE_USHORT_TYPEDEF
#pragma GCC poison HAVE_WAIT3
#pragma GCC poison INCLUDE_LIBC_H_AS_CXX
#pragma GCC poison INCLUDE_MATH_H_AS_CXX
#pragma GCC poison TM_IN_SYS_TIME
#endif
+#if !defined(POISON_DEPRECATED_FEATURE_MACROS) || !defined(__GNUC__)
/* #undef C_INLINE */
+/* #undef HAVE_BCMP */
/* #undef HAVE_BCOPY */
+/* #undef HAVE_CONTIGUOUS_ITERATOR_CATEGORY */
+/* #undef HAVE_DECLARATION_FP_EXCEPT_T */
/* #undef HAVE_DECLARATION_STD__IOS_BASE__OPENMODE */
/* #undef HAVE_DOPRNT */
/* #undef HAVE_EMPTY_ARGC_ARGV */
+/* #undef HAVE_FINITE */
/* #undef HAVE_FSTREAM_H */
+/* #undef HAVE_GETRUSAGE */
+/* #undef HAVE_INDEX */
+/* #undef HAVE_INTP_ACCEPT */
+/* #undef HAVE_INTP_GETSOCKOPT */
/* #undef HAVE_IOMANIP_H */
/* #undef HAVE_IOSTREAM_H */
/* #undef HAVE_IOS_NOCREATE */
+/* #undef HAVE_ITOA */
/* #undef HAVE_LIBIOSTREAM */
+/* #undef HAVE_LIBNSL */
+/* #undef HAVE_LIBSOCKET */
+/* #undef HAVE_LISTEN */
/* #undef HAVE_LONGLONG */
+/* #undef HAVE_MALLOC_H */
/* #undef HAVE_MEMORY_H */
/* #undef HAVE_NDIR_H */
/* #undef HAVE_NEW_H */
/* #undef HAVE_OLD_READDIR_R */
+/* #undef HAVE_PROTOTYPE_FINITE */
+/* #undef HAVE_PROTOTYPE_MKSTEMP */
+/* #undef HAVE_PROTOTYPE_NANOSLEEP */
/* #undef HAVE_PROTOTYPE_STD__FINITE */
/* #undef HAVE_PROTOTYPE_WAIT3 */
+/* #undef HAVE_PROTOTYPE_FEENABLEEXCEPT */
+/* #undef HAVE_PROTOTYPE__FPCLASSF */
+/* #undef HAVE_RINDEX */
+/* #undef HAVE_SIGJMP_BUF */
/* #undef HAVE_SSTREAM_H */
/* #undef HAVE_STAT_H */
/* #undef HAVE_STREAMBUF_H */
/* #undef HAVE_STRSTREAM_H */
/* #undef HAVE_STRSTREA_H */
+/* #undef HAVE_SYSTEM_ERROR */
+/* #undef HAVE_SYS_ERRNO_H */
/* #undef HAVE_SYS_NDIR_H */
+/* #undef HAVE_TUPLE */
+/* #undef HAVE_UCHAR_TYPEDEF */
+/* #undef HAVE_UINT_TYPEDEF */
/* #undef HAVE_ULONGLONG */
+/* #undef HAVE_ULONG_TYPEDEF */
+/* #undef HAVE_USHORT_TYPEDEF */
/* #undef HAVE_WAIT3 */
/* #undef INCLUDE_LIBC_H_AS_CXX */
/* #undef INCLUDE_MATH_H_AS_CXX */
/* #undef RETSIGTYPE */
/* #undef TM_IN_SYS_TIME */
/* #undef __CHAR_UNSIGNED__ */
-
+#define SIZEOF_DOUBLE 8
+#define SIZEOF_FLOAT 4
+#define SIZEOF_SHORT 2
+#endif
/* Historical feature tests for BSD socket functions, which exist on POSIX
* systems and on Windows. These are not tested anymore.
# Minimum CMake version required
-cmake_minimum_required(VERSION 3.7.0...3.31.2 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.7.0...4.2.0 FATAL_ERROR)
# Declare project
project(DCMTK)
get_filename_component(FILE "${DICTIONARY}" NAME)
set(DCMDICTPATH "${DCMDICTPATH}:${ANDROID_TEMPORARY_FILES_LOCATION}/${FILE}")
endforeach()
+ set(DCMICONVPATH "${ANDROID_TEMPORARY_FILES_LOCATION}/data")
configure_file("${DCMTK_SOURCE_DIR}/CMake/CTest/CTestCustomAndroid.cmake.in"
"${DCMTK_BINARY_DIR}/CTestCustom.cmake" ESCAPE_QUOTES @ONLY
)
copyright:
/*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved.
*
* This software and supporting documentation were developed by
---------------------------------------------------------------------------
-Copyright (C) 2008-2024, OFFIS e.V. and ICSMED AG, Oldenburg, Germany.
-Copyright (C) 2013-2024, J. Riesmeier, Oldenburg, Germany.
+Copyright (C) 2008-2025, OFFIS e.V. and ICSMED AG, Oldenburg, Germany.
+Copyright (C) 2013-2025, J. Riesmeier, Oldenburg, Germany.
All rights reserved.
Redistribution and use in source and binary forms, with or without
---------------------------------------------------------------------------
-Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany.
+Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany.
All rights reserved.
Redistribution and use in source and binary forms, with or without
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
-
---------------------------------------------------------------------------
The implementation of the getLastErrorString() function in ofstub.cc
---------------------------------------------------------------------------
+The implementation of the JSON to DICOM converter available uses the
+"jsmn" JSON parser library with the following license:
+
+/*
+ * MIT License
+ *
+ * Copyright (c) 2010 Serge Zaitsev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+---------------------------------------------------------------------------
+
Finally, DCMTK can be configured and compiled to make use of a number of
optional external libraries that, when available, provide added functionality
such as compression, encryption, or support for certain image formats.
Open Source DICOM Toolkit DCMTK:
Carl Zeiss Meditec: The preparation and publication of the DCMTK 3.6.2 release
- as well as several extensions in wlmscpfs and dcmqrscp were supported by
+ as well as several extensions in "wlmscpfs" and "dcmqrscp" were supported by
funding from Carl Zeiss Meditec AG (Muenchen, Germany).
DKFZ: The work on the DCMTK module "dcmrt" was supported in part by funding
tool "dcmrecv" and the underlying class "DcmStorageSCP".
GE Aviation: GE Aviation supported DCMTK by sponsoring the development of the
- dcmect library and basic concatenation support in dcmfg.
+ "dcmect" library and basic concatenation support in "dcmfg".
ICSMED: From 2006 to 2012, the work on the DCMTK was supported by employees of
the ICSMED AG (Oldenburg, Germany), a spin-off from the OFFIS institute.
reports possible issues to the DCMTK team. He was also responsible for
packaging the DCMTK library and tools for the Debian operating system.
-Mathworks: Funded implementation of TLS support in getscu, introduced
+Mathworks: Funded implementation of TLS support in "getscu", introduced
in DCMTK 3.6.9.
Medpace: Funded the development of the "dcm2img" tool introduced in DCMTK
initiative, to project Open Source Diffusion MRI Technology For Brain Cancer
Research, award U01 CA199459.
+Twisted Ceptors: Funded the extension of the "storescp" application by the
+ "--max-associations" option that allows the user to limit the number of
+ clients served in parallel when operating in "--fork mode".
+
VISUS: The work on various extensions of the DCMTK was supported in part by
funding from the VISUS Technology Transfer GmbH (Bochum, Germany).
Please note that this list does not claim to be exhaustive. Just send us an
email if you think that you or your company/organization should also be listed.
-DCMTK Team, 2024-11-21
+DCMTK Team, 2025-12-15
The DICOM toolkit (DCMTK) needs to be compiled with a C++ compiler. We
recommend using the GNU C++ compiler in versions higher than 9.5.0 (most of the
development for this release was done using GNU gcc 12.2.0 on Debian Linux and
-GNU gcc 13.2.0 on Ubuntu Linux). The software is also known to compile using
+GNU gcc 13.3.0 on Ubuntu Linux). The software is also known to compile using
Clang and Microsoft Visual Studio.
Compatibility with other C++ compilers is unknown, however, we have tried to
The DCMTK software can be compiled under a native Microsoft Windows environment
(see section "Microsoft Windows with CMake" below for more information).
-The current DCMTK software release 3.6.9 successfully compiles on the following
+The current DCMTK software release 3.7.0 successfully compiles on the following
operating system / hardware / compiler combinations:
Windows 10 / Intel x86 / Microsoft Visual C++ 2017 Community (VS 15)
Unix (or lookalikes)
--------------------
-The current DCMTK software release 3.6.9 successfully compiles on the following
+The current DCMTK software release 3.7.0 successfully compiles on the following
operating system / hardware / compiler combinations using the instructions
given below:
+ FreeBSD 14.3 / amd64|x86_64 / Clang 19.1.7
+ Linux 5.14.0 / amd64|x86_64 / GNU gcc 11.5.0 (AlmaLinux 9.6)
+ Linux 6.1.0 / Intel x86 / Clang 14.0.6 (Debian 12)
+ Linux 6.1.0 / Intel x86 / GNU gcc 12.2.0 (Debian 12)
+ Linux 6.1.0 / amd64|x86_64 / Clang 14.0.6 (Debian 12)
+ Linux 6.1.0 / amd64|x86_64 / GNU gcc 12.2.0 (Debian 12)
+ Linux 6.1.0 / amd64|x86_64 / GNU gcc 13.2.1 (Alpine 3.20 musl libc)
+ Linux 6.8.0 / amd64|x86_64 / GNU gcc 11.5.0 (Ubuntu 24.04.3 LTS)
+ Linux 6.8.0 / amd64|x86_64 / GNU gcc 12.4.0 (Ubuntu 24.04.3 LTS)
+ Linux 6.8.0 / amd64|x86_64 / GNU gcc 13.3.0 (Ubuntu 24.04.3 LTS)
+ Linux 6.8.0 / amd64|x86_64 / GNU gcc 14.2.0 (Ubuntu 24.04.3 LTS)
+ Linux 6.8.0 / amd64|x86_64 / Clang 18.1.3 (Ubuntu 24.04.3 LTS)
+ Linux 6.8.0 / s390x / GNU gcc 13.3.0 (Ubuntu 24.04.2 LTS)
+ Linux 6.8.0 / s390x / Clang 18.1.3 (Ubuntu 24.04.2 LTS)
+ MacOS X 15.5 / amd64|x86_64 / Apple Clang 17.0.0
+ MacOS X 15.5 / amd64|x86_64 / GNU gcc 15.2.0
+ MacOS X 15.5 / arm64 / Apple Clang 17.0.0
+ MacOS X 15.5 / arm64 / GNU gcc 15.2.0
+ NetBSD 10.1 / amd64|x86_64 / Clang 18.1.8
+ NetBSD 10.1 / amd64|x86_64 / GNU gcc 10.5.0
+ OpenBSD 7.7 / amd64|x86_64 / Clang 16.0.6
+ OpenIndiana / amd64|x86_64 / GNU gcc 14.3.0 (OpenIndiana 2025.06)
+
+
+Cross Compiling
+---------------
+
+For target platforms other than Android, see section "CROSS COMPILING WITH
+CMAKE" below. For Android, the current DCMTK release can be cross-compiled
+targeting the following platform:
+
+ Android / arm64 / Clang 18.0.1 (API 35, ABI arm64-v8a)
+
+Cross compiling support with running configuration and unit tests is provided
+using CMake and requires the use of the Android emulator or Wine when targeting
+Android or Windows respectively. Other versions of Android may also work,
+but the above mentioned one is currently the only one that is being
+regularly tested.
+
+
+Other Platforms
+---------------
+
+The previous release DCMTK 3.6.9 was also tested on the following platforms
+that may still work, but were not tested again for this release:
+
+ Android / arm64 / GNU gcc 12.2.0 (API 24, ABI arm64-v8a)
FreeBSD 14.1 / amd64|x86_64 / Clang 18.1.5
Linux 4.19.0 / ppc64le / IBM XL C/C++ 16.1.1 Community
Linux 5.14.0 / amd64|x86_64 / GNU gcc 11.4.1 (AlmaLinux 9.4)
OpenBSD 7.5 / amd64|x86_64 / Clang 16.0.6
OpenIndiana / amd64|x86_64 / GNU gcc 13.2.0 (OpenIndiana 2023.10)
-
-Cross Compiling
----------------
-
-For target platforms other than Android, see section "CROSS COMPILING WITH
-CMAKE" below. For Android, the current DCMTK release can be cross-compiled
-targeting the following platform:
-
- Android / arm64 / GNU gcc 12.2.0 (API 24, ABI arm64-v8a)
-
-Cross compiling support with running configuration and unit tests is provided
-using CMake and requires the use of the Android emulator or Wine when targeting
-Android or Windows respectively. Other versions of Android will most likely
-also work, but the above mentioned one is currently the only one that is being
-regularly tested.
-
-Other Platforms
----------------
-
The previous release DCMTK 3.6.8 was also tested on the following platforms
that may still work, but were not tested again for this release:
Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2019 Community (VS 16)
Windows 7 / amd64|x86_64 / MinGW gcc 9.2.0 (x86_64-w64-mingw32)
-The previous release DCMTK 3.6.7 was also tested on the following platforms
-that may still work, but were not tested again for this release:
-
- Windows 7 / Intel x86 / Microsoft Visual C++ 2010 Express (VS 10)
- Windows 7 / amd64|x86_64 / Microsoft Visual C++ 2010 Express (VS 10)
- Windows 7 / amd64|x86_64 / Cygwin GCC 7.4.0 (x86_64-pc-cygwin)
- Windows 10 / Intel x86 / MinGW gcc 11.2.0 (i686-w64-mingw32)
- Windows 10 / Intel x86 / MinGW Clang 13.0.0 (i686-w64-windows-gnu)
- Windows 10 / amd64|x86_64 / MinGW gcc 11.2.0 (x86_64-w64-mingw32)
- Windows 10 / amd64|x86_64 / MinGW Clang 13.0.0 (x86_64-w64-windows-gnu)
- FreeBSD 13.0 / amd64|x86_64 / Clang 11.0.1
- Linux 4.19.0 / amd64|x86_64 / Clang 7.0.1 (Debian 10)
- Linux 4.19.0 / amd64|x86_64 / GNU 10.3.1 (Alpine 3.15.0 with musl libc)
- Linux 4.19.0 / amd64|x86_64 / GNU gcc 8.3.0 (Debian 10)
- Linux 4.19.0 / amd64|x86_64 / GNU gcc 8.3.0 (Debian 10)
- Linux 5.10.0 / Intel x86 / GNU gcc 10.2.1 (Debian 11)
- Linux 5.4.0 / amd64|x86_64 / Clang 10.0.0 (Ubuntu 20.04)
- Linux 5.4.0 / amd64|x86_64 / Clang 9.0.1 (Ubuntu 20.04)
- Linux 5.4.0 / amd64|x86_64 / GNU gcc 10.3.0 (Ubuntu 20.04)
- Linux 5.4.0 / amd64|x86_64 / GNU gcc 9.3.0 (Ubuntu 20.04)
- Linux 5.13.0 / amd64|x86_64 / Clang 13.0.0-2 (Ubuntu 21.10)
- Linux 5.13.0 / amd64|x86_64 / GNU gcc 11.2.0 (Ubuntu 21.10)
- MacOS X 10.15 / amd64|x86_64 / Apple Clang 11.0.0
- MacOS X 10.15 / amd64|x86_64 / GNU gcc 9.2.0
- NetBSD 9.0 / amd64|x86_64 / Clang 10.0.1
- NetBSD 9.0 / amd64|x86_64 / GNU gcc 7.5.0
- OpenBSD 7.0 / amd64|x86_64 / Clang 11.1.1
Earlier releases of the DCMTK are known to also compile on further platforms,
which are not available to us for testing purposes any more, e.g. AIX, HP-UX,
This release of DCMTK requires OpenSSL release 1.1.1 or newer. Users should
make sure that the most recent OpenSSL patch level is applied. This release of
-DCMTK is known to compile with OpenSSL releases 1.1.1 as well as 3.0.x to 3.4.x.
+DCMTK is known to compile with OpenSSL releases 1.1.1 as well as 3.0.x to 3.6.x.
When using CMake, if support for security enhancements is desired, a compiled
version of the OpenSSL libraries and include files must be available during
DCMTK supports the conversion of DICOM images to TIFF. DCMTK relies on the
libtiff toolkit (www.libtiff.org) for this purpose. This release of DCMTK is
-known to compile with libtiff releases 4.5.0 to 4.7.0, although other releases
+known to compile with libtiff release 4.7.1, although other releases
may work as well.
When using CMake, a compiled version of the libtiff libraries and include files
DCMTK supports the conversion of DICOM images to PNG. DCMTK relies on the
libpng toolkit (www.libpng.org) for this purpose. This release of DCMTK is
-known to compile with libpng releases 1.6.39 to 1.6.44, although other releases
+known to compile with libpng releases 1.6.47 to 1.6.51, although other releases
may work as well.
When using CMake, a compiled version of the libpng libraries and include files
DCMTK supports the conversion of XML documents to DICOM files. DCMTK relies on
the libxml2 toolkit (www.libxml.org) for this purpose. This release of DCMTK
-is known to compile with libxml2 releases 2.9.14 to 2.13.4, although other
+is known to compile with libxml2 releases 2.13.9 to 2.15.1, although other
releases may work as well.
When using CMake, if support for XML import is desired, a compiled version of
By default, DCMTK will compile with "CMAKE_CXX_STANDARD" set to "11" (CXX11).
The user can choose to build with a newer C++ standard by setting
"CMAKE_CXX_STANDARD" accordingly. The following versions are supported:
+
- 11 (CXX11)
- 14 (CXX14)
- 17 (CXX17)
- 20 (CXX20)
-DCMTK will still compile with "CMAKE_CXX_STANDARD" set to "98" (CXX98), but
-support will be removed in future versions of DCMTK.
+Compilation of DCMTK with C++98 is deprecated. In this release, it can be
+enabled by setting "CMAKE_CXX_STANDARD=98" and "DCMTK_PERMIT_CXX98=ON", but
+support for C++ releases before C++11 will be removed in future versions
+of DCMTK.
Using C++11 or later will change some parts of DCMTK's API, so a C++11 build of
DCMTK is potentially incompatible with a classic (C++98) build of DCMTK. This
CMake which will generate suitable build files for all of DCMTK's projects from
these files.
-DCMTK 3.6.9 requires CMake version 3.7.0 or later. We recommend using the
-latest stable release of CMake (currently version 3.31.2) since newer versions
+DCMTK 3.7.0 requires CMake version 3.7.0 or later. We recommend using the
+latest stable release of CMake (currently version 4.2.0) since newer versions
of CMake often provide better output in case of errors and are generally easier
to use (for example, by providing better support for detecting the availability
of third-party libraries). If possible, use the CMake version your operating
1. Go to Start -> Programs -> CMake -> "CMake" or "CMake (cmake-gui)" to start
the CMake utility through which the configuration can be done.
2. In the entry field "Where is the source code:" enter the directory in which
- the DCMTK source code resides, e.g. "C:\dcmtk-3.6.9".
+ the DCMTK source code resides, e.g. "C:\dcmtk-3.7.0".
3. In the entry field "Where to build the binaries:" enter the directory in
which the libraries and binaries are to be built, e.g. "C:\dcmtk-msvc16".
4. In the combobox "Build for:" or "Specify the generator for this project:"
example, in order to turn on libxml2 support, set the value of variable
"DCMTK_WITH_XML" to "ON" and set the value of variable "WITH_LIBXMLINC" to
the path where the include files and libraries of libxml2 can be found, e.g.
- "C:\libxml2-2.13.4". The support of all other external libraries can be
+ "C:\libxml2-2.15.1". The support of all other external libraries can be
turned on in a similar way:
libpng support:
set "DCMTK_WITH_PNG" to "ON" and
- set "WITH_LIBPNGINC" e.g. to "C:\libpng-1.6.44"
+ set "WITH_LIBPNGINC" e.g. to "C:\libpng-1.6.51"
libtiff support:
set "DCMTK_WITH_TIFF" to "ON" and
- set "WITH_LIBTIFFINC" e.g. to "C:\libtiff-4.7.0"
+ set "WITH_LIBTIFFINC" e.g. to "C:\libtiff-4.7.1"
OpenSSL support:
set "DCMTK_WITH_OPENSSL" to "ON" and
- set "WITH_OPENSSLINC" e.g. to "C:\openssl-3.4.0"
+ set "WITH_OPENSSLINC" e.g. to "C:\openssl-3.6.0"
zlib support:
set "DCMTK_WITH_ZLIB" to "ON" and
set "WITH_ZLIBINC" e.g. to "C:\zlib-1.3.1"
- libiconv support:
- set "DCMTK_WITH_ICONV" to "ON" and
- set "WITH_LIBICONVINC" e.g. to "C:\libiconv-1.17"
-
In order to turn the support of a certain external library off, set the
value of the corresponding variable ("DCMTK_WITH_XML", "DCMTK_WITH_PNG",
- "DCMTK_WITH_TIFF", "DCMTK_WITH_OPENSSL", "DCMTK_WITH_ZLIB" or
- "DCMTK_WITH_ICONV") to "OFF".
+ "DCMTK_WITH_TIFF", "DCMTK_WITH_OPENSSL" or "DCMTK_WITH_ZLIB") to "OFF".
(Please note that the include files of all external libraries are always
expected in a directory named "include" below the directory that is
specified in "WITH_LIBXMLINC", "WITH_LIBPNGINC", "WITH_LIBTIFFINC",
- "WITH_OPENSSLINC", "WITH_ZLIBINC" or "WITH_LIBICONVINC".)
+ "WITH_OPENSSLINC" or "WITH_ZLIBINC".)
(Please note also that the library files of all external libraries are always
expected in directory named "lib" below the directory that is specified in
- "WITH_LIBXMLINC", "WITH_LIBPNGINC", "WITH_LIBTIFFINC", "WITH_OPENSSLINC",
- "WITH_ZLIBINC" or "WITH_LIBICONV". Moreover, note that the following
+ "WITH_LIBXMLINC", "WITH_LIBPNGINC", "WITH_LIBTIFFINC", "WITH_OPENSSLINC"
+ or "WITH_ZLIBINC". Moreover, note that the following
filenames must be used for the corresponding lib files:
libxml2:
"zlib_d.lib" - debug version
"zlib_o.lib" - release version (optimized)
- libiconv: (* See note below)
- "libiconv_d.lib" - debug version
- "libiconv_o.lib" - release version (optimized)
- "libchset_d.lib" - debug version
- "libchset_o.lib" - release version (optimized)
+ The debug and release versions of all libraries must be compiled with the
+ same runtime library dependency as DCMTK (i.e., /MT[d] or /MD[d]).
+ By default, DCMTK is compiled with /MTd for Debug and /MT for Release mode
+ unless the CMake variables "DCMTK_COMPILE_WIN32_MULTITHREADED_DLL" or
+ "BUILD_SHARED_LIBS" (see below) are set to true, in which case DCMTK is
+ compiled with /MDd for Debug and /MD for Release mode.
- The debug versions of all libraries must be compiled for the multithread
- debug version of the runtime (/MTd), the release version must be compiled
- for the non-debug multithread runtime (/MT). Precompiled versions of all
- libraries (*) can be downloaded from https://dcmtk.org/develop/#lib-win .
+ Precompiled versions of all libraries can be downloaded from
+ https://dcmtk.org/develop/#lib-win .
- (*) Starting with DCMTK 3.6.8, libiconv is no longer part of the download
- package. That also means that libxml2 was built without this library.
- Therefore, DCMTK tools that read XML files will only support UTF-8 and
- Latin-1 encoding.
In the CMake GUI, there are a few more settings that can be modified
to affect the way DCMTK is compiled. The most important of these are:
The typical way to build DCMTK on Unix-like systems with CMake is as follows
(if not using the GUI, in that case look at the description for Windows above):
- mkdir dcmtk-3.6.9-build
- cd dcmtk-3.6.9-build
- cmake ../dcmtk-3.6.9
+ mkdir dcmtk-3.7.0-build
+ cd dcmtk-3.7.0-build
+ cmake ../dcmtk-3.7.0
make -j8
- make DESTDIR=../dcmtk-3.6.9-install install
+ make DESTDIR=../dcmtk-3.7.0-install install
The above commands assume that the DCMTK source code was extracted to the
-current working directory into a folder named "dcmtk-3.6.9". DCMTK will be
+current working directory into a folder named "dcmtk-3.7.0". DCMTK will be
configured using CMake with the default options, detecting and including all
available support libraries and then compiled using eight CPU cores
("make -j8", adjust as needed). The result will be installed to the directory
-"dcmtk-3.6.9-install" next to the source code directory.
+"dcmtk-3.7.0-install" next to the source code directory.
If you want to modify your build configuration, like enabling or disabling some
features of DCMTK (e.g. PNG support), or if you need to modify the predefined
build variables, you can use the curses-based CMake configuration tool ccmake.
First, create the initial build setup (system check) and then call "ccmake":
- mkdir dcmtk-3.6.9-build
- cd dcmtk-3.6.9-build
- cmake ../dcmtk-3.6.9
- ccmake ../dcmtk-3.6.9
+ mkdir dcmtk-3.7.0-build
+ cd dcmtk-3.7.0-build
+ cmake ../dcmtk-3.7.0
+ ccmake ../dcmtk-3.7.0
Now you can modify the configuration values. Please see the help on the bottom
of the screen. When finished, press "c" to generate a new build configuration,
the ccmake step above and call "cmake" directly with the desired values set.
Example for a build with TCP wrapper disabled:
- mkdir dcmtk-3.6.9-build
- cd dcmtk-3.6.9-build
- cmake -DDCMTK_WITH_WRAP:BOOL=FALSE ../dcmtk-3.6.9
+ mkdir dcmtk-3.7.0-build
+ cd dcmtk-3.7.0-build
+ cmake -DDCMTK_WITH_WRAP:BOOL=FALSE ../dcmtk-3.7.0
...
The format is "NAME:TYPE=VALUE". Use ccmake to find out the variable names and
Most DCMTK modules have been documented with Doxygen (www.doxygen.org), a free
source code documentation system similar to Javadoc. Unix users who have
Doxygen installed can create a hypertext documentation with "make html" in the
-"dcmtk-3.6.9" or "doxygen" directory; Windows and other CMake users should
+"dcmtk-3.7.0" or "doxygen" directory; Windows and other CMake users should
build the "DOXYGEN" target. A project file for Microsoft's HTML Help Workshop
can also be generated allowing to create a single CHM file (compressed HTML)
from the documentation. Other output formats (e.g. LaTeX) can be enabled by
DCMTK's top-level main directory has been removed as the final warning for users
of the Autoconf toolchain. If you prefer to build DCMTK with Autoconf, however,
this is still possible. Perform the following steps from the top-level
-("dcmtk-3.6.9") directory to compile and install the software:
+("dcmtk-3.7.0") directory to compile and install the software:
Step 0:
cd config
"--prefix" when compiling and installing OpenSSL.
For example, if you wish to enable the security enhancements, and OpenSSL is
-installed in "/usr/local/apps/openssl-3.4.0", you should start configure as:
+installed in "/usr/local/apps/openssl-3.6.0", you should start configure as:
./configure --ignore-deprecation
- --with-opensslinc=/usr/local/apps/openssl-3.4.0
+ --with-opensslinc=/usr/local/apps/openssl-3.6.0
Configure will assume that the OpenSSL include files are installed in
-"/usr/local/apps/openssl-3.4.0/include" and will expect the library in
-"/usr/local/apps/openssl-3.4.0/lib". Appropriate options will be passed to
+"/usr/local/apps/openssl-3.6.0/include" and will expect the library in
+"/usr/local/apps/openssl-3.6.0/lib". Appropriate options will be passed to
the compiler and the linker.
Support for zlib, libtiff, libpng, libxml2, libwrap, and/or libiconv can be
./configure --ignore-deprecation
--with-libzlibinc=/usr/local/apps/zlib-1.3.1
- --with-libtiffinc=/usr/local/apps/libtiff-4.7.0
- --with-libpnginc=/usr/local/apps/libpng-1.6.44
- --with-libxmlinc=/usr/local/apps/libxml2-2.13.4
+ --with-libtiffinc=/usr/local/apps/libtiff-4.7.1
+ --with-libpnginc=/usr/local/apps/libpng-1.6.51
+ --with-libxmlinc=/usr/local/apps/libxml2-2.15.1
--with-libwrapinc=/usr/local/apps/tcp_wrappers-7.6
--with-libiconvinc=/usr/local/apps/libiconv-1.17
Have fun.
-M. Eichelberg, J. Riesmeier, M. Onken, T. Xu
+M. Eichelberg, J. Riesmeier, M. Onken, T. Xu, H. Roesen
DCMTK Development Team, Oldenburg, Germany.
-Last revised: 2024-12-10 (Onken)
+Last revised: 2025-12-02 (Riesmeier)
.NOTPARALLEL:
-all: config-all oficonv-all ofstd-all oflog-all dcmdata-all dcmiod-all dcmfg-all dcmseg-all dcmimgle-all dcmimage-all dcmjpeg-all dcmjpls-all dcmtls-all dcmnet-all dcmsr-all dcmsign-all dcmwlm-all dcmqrdb-all dcmpstat-all dcmrt-all dcmtract-all dcmpmap-all dcmect-all dcmapps-all
+all: config-all oficonv-all ofstd-all oflog-all dcmdata-all dcmimgle-all dcmimage-all dcmjpeg-all dcmjpls-all dcmtls-all dcmnet-all dcmsr-all dcmsign-all dcmwlm-all dcmqrdb-all dcmrt-all dcmiod-all dcmpstat-all dcmfg-all dcmseg-all dcmtract-all dcmpmap-all dcmect-all dcmapps-all
-libsrc-all: oficonv-libsrc-all ofstd-libsrc-all oflog-libsrc-all dcmdata-libsrc-all dcmiod-libsrc-all dcmfg-libsrc-all dcmseg-libsrc-all dcmimgle-libsrc-all dcmimage-libsrc-all dcmjpeg-libsrc-all dcmjpls-libsrc-all dcmtls-libsrc-all dcmnet-libsrc-all dcmsr-libsrc-all dcmsign-libsrc-all dcmwlm-libsrc-all dcmqrdb-libsrc-all dcmpstat-libsrc-all dcmrt-libsrc-all dcmtract-libsrc-all dcmpmap-libsrc-all dcmect-libsrc-all dcmapps-libsrc-all
+libsrc-all: oficonv-libsrc-all ofstd-libsrc-all oflog-libsrc-all dcmdata-libsrc-all dcmimgle-libsrc-all dcmimage-libsrc-all dcmjpeg-libsrc-all dcmjpls-libsrc-all dcmtls-libsrc-all dcmnet-libsrc-all dcmsr-libsrc-all dcmsign-libsrc-all dcmwlm-libsrc-all dcmqrdb-libsrc-all dcmrt-libsrc-all dcmiod-libsrc-all dcmpstat-libsrc-all dcmfg-libsrc-all dcmseg-libsrc-all dcmtract-libsrc-all dcmpmap-libsrc-all dcmect-libsrc-all dcmapps-libsrc-all
-tests-all: config-tests-all oficonv-tests-all ofstd-tests-all oflog-tests-all dcmdata-tests-all dcmiod-tests-all dcmfg-tests-all dcmseg-tests-all dcmimgle-tests-all dcmimage-tests-all dcmjpeg-tests-all dcmjpls-tests-all dcmtls-tests-all dcmnet-tests-all dcmsr-tests-all dcmsign-tests-all dcmwlm-tests-all dcmqrdb-tests-all dcmpstat-tests-all dcmrt-tests-all dcmtract-tests-all dcmpmap-tests-all dcmect-tests-all dcmapps-tests-all
+tests-all: config-tests-all oficonv-tests-all ofstd-tests-all oflog-tests-all dcmdata-tests-all dcmimgle-tests-all dcmimage-tests-all dcmjpeg-tests-all dcmjpls-tests-all dcmtls-tests-all dcmnet-tests-all dcmsr-tests-all dcmsign-tests-all dcmwlm-tests-all dcmqrdb-tests-all dcmrt-tests-all dcmiod-tests-all dcmpstat-tests-all dcmfg-tests-all dcmseg-tests-all dcmtract-tests-all dcmpmap-tests-all dcmect-tests-all dcmapps-tests-all
-install: config-install oficonv-install ofstd-install oflog-install dcmdata-install dcmiod-install dcmfg-install dcmseg-install dcmimgle-install dcmimage-install dcmjpeg-install dcmjpls-install dcmtls-install dcmnet-install dcmsr-install dcmsign-install dcmwlm-install dcmqrdb-install dcmpstat-install dcmrt-install dcmtract-install dcmpmap-install dcmect-install dcmapps-install dcmtk-install-doc install-man
+install: config-install oficonv-install ofstd-install oflog-install dcmdata-install dcmimgle-install dcmimage-install dcmjpeg-install dcmjpls-install dcmtls-install dcmnet-install dcmsr-install dcmsign-install dcmwlm-install dcmqrdb-install dcmrt-install dcmiod-install dcmpstat-install dcmfg-install dcmseg-install dcmtract-install dcmpmap-install dcmect-install dcmapps-install dcmtk-install-doc install-man
install-all: install install-lib install-html
-install-bin: config-install-bin oficonv-install-bin ofstd-install-bin oflog-install-bin dcmdata-install-bin dcmiod-install-bin dcmfg-install-bin dcmseg-install-bin dcmimgle-install-bin dcmimage-install-bin dcmjpeg-install-bin dcmjpls-install-bin dcmtls-install-bin dcmnet-install-bin dcmsr-install-bin dcmsign-install-bin dcmwlm-install-bin dcmqrdb-install-bin dcmpstat-install-bin dcmrt-install-bin dcmtract-install-bin dcmpmap-install-bin dcmect-install-bin dcmapps-install-bin
+install-bin: config-install-bin oficonv-install-bin ofstd-install-bin oflog-install-bin dcmdata-install-bin dcmimgle-install-bin dcmimage-install-bin dcmjpeg-install-bin dcmjpls-install-bin dcmtls-install-bin dcmnet-install-bin dcmsr-install-bin dcmsign-install-bin dcmwlm-install-bin dcmqrdb-install-bin dcmrt-install-bin dcmiod-install-bin dcmpstat-install-bin dcmfg-install-bin dcmseg-install-bin dcmtract-install-bin dcmpmap-install-bin dcmect-install-bin dcmapps-install-bin
-install-doc: config-install-doc oficonv-install-doc ofstd-install-doc oflog-install-doc dcmdata-install-doc dcmiod-install-doc dcmfg-install-doc dcmseg-install-doc dcmimgle-install-doc dcmimage-install-doc dcmjpeg-install-doc dcmjpls-install-doc dcmtls-install-doc dcmnet-install-doc dcmsr-install-doc dcmsign-install-doc dcmwlm-install-doc dcmqrdb-install-doc dcmpstat-install-doc dcmrt-install-doc dcmtract-install-doc dcmpmap-install-doc dcmect-install-doc dcmapps-install-doc
+install-doc: config-install-doc oficonv-install-doc ofstd-install-doc oflog-install-doc dcmdata-install-doc dcmimgle-install-doc dcmimage-install-doc dcmjpeg-install-doc dcmjpls-install-doc dcmtls-install-doc dcmnet-install-doc dcmsr-install-doc dcmsign-install-doc dcmwlm-install-doc dcmqrdb-install-doc dcmrt-install-doc dcmiod-install-doc dcmpstat-install-doc dcmfg-install-doc dcmseg-install-doc dcmtract-install-doc dcmpmap-install-doc dcmect-install-doc dcmapps-install-doc
-install-data: config-install-data oficonv-install-data ofstd-install-data oflog-install-data dcmdata-install-data dcmiod-install-data dcmfg-install-data dcmseg-install-data dcmimgle-install-data dcmimage-install-data dcmjpeg-install-data dcmjpls-install-data dcmtls-install-data dcmnet-install-data dcmsr-install-data dcmsign-install-data dcmwlm-install-data dcmqrdb-install-data dcmpstat-install-data dcmrt-install-data dcmtract-install-data dcmpmap-install-data dcmect-install-data dcmapps-install-data
+install-data: config-install-data oficonv-install-data ofstd-install-data oflog-install-data dcmdata-install-data dcmimgle-install-data dcmimage-install-data dcmjpeg-install-data dcmjpls-install-data dcmtls-install-data dcmnet-install-data dcmsr-install-data dcmsign-install-data dcmwlm-install-data dcmqrdb-install-data dcmrt-install-data dcmiod-install-data dcmpstat-install-data dcmfg-install-data dcmseg-install-data dcmtract-install-data dcmpmap-install-data dcmect-install-data dcmapps-install-data
-install-etc: config-install-etc oficonv-install-etc ofstd-install-etc oflog-install-etc dcmdata-install-etc dcmiod-install-etc dcmfg-install-etc dcmseg-install-etc dcmimgle-install-etc dcmimage-install-etc dcmjpeg-install-etc dcmjpls-install-etc dcmtls-install-etc dcmnet-install-etc dcmsr-install-etc dcmsign-install-etc dcmwlm-install-etc dcmqrdb-install-etc dcmpstat-install-etc dcmrt-install-etc dcmtract-install-etc dcmpmap-install-etc dcmect-install-etc dcmapps-install-etc
+install-etc: config-install-etc oficonv-install-etc ofstd-install-etc oflog-install-etc dcmdata-install-etc dcmimgle-install-etc dcmimage-install-etc dcmjpeg-install-etc dcmjpls-install-etc dcmtls-install-etc dcmnet-install-etc dcmsr-install-etc dcmsign-install-etc dcmwlm-install-etc dcmqrdb-install-etc dcmrt-install-etc dcmiod-install-etc dcmpstat-install-etc dcmfg-install-etc dcmseg-install-etc dcmtract-install-etc dcmpmap-install-etc dcmect-install-etc dcmapps-install-etc
-install-lib: config-install-lib oficonv-install-lib ofstd-install-lib oflog-install-lib dcmdata-install-lib dcmiod-install-lib dcmfg-install-lib dcmseg-install-lib dcmimgle-install-lib dcmimage-install-lib dcmjpeg-install-lib dcmjpls-install-lib dcmtls-install-lib dcmnet-install-lib dcmsr-install-lib dcmsign-install-lib dcmwlm-install-lib dcmqrdb-install-lib dcmpstat-install-lib dcmrt-install-lib dcmtract-install-lib dcmpmap-install-lib dcmect-install-lib dcmapps-install-lib
+install-lib: config-install-lib oficonv-install-lib ofstd-install-lib oflog-install-lib dcmdata-install-lib dcmimgle-install-lib dcmimage-install-lib dcmjpeg-install-lib dcmjpls-install-lib dcmtls-install-lib dcmnet-install-lib dcmsr-install-lib dcmsign-install-lib dcmwlm-install-lib dcmqrdb-install-lib dcmrt-install-lib dcmiod-install-lib dcmpstat-install-lib dcmfg-install-lib dcmseg-install-lib dcmtract-install-lib dcmpmap-install-lib dcmect-install-lib dcmapps-install-lib
-install-include: config-install-include oficonv-install-include ofstd-install-include oflog-install-include dcmdata-install-include dcmiod-install-include dcmfg-install-include dcmseg-install-include dcmimgle-install-include dcmimage-install-include dcmjpeg-install-include dcmjpls-install-include dcmtls-install-include dcmnet-install-include dcmsr-install-include dcmsign-install-include dcmwlm-install-include dcmqrdb-install-include dcmpstat-install-include dcmrt-install-include dcmtract-install-include dcmpmap-install-include dcmect-install-include dcmapps-install-include
+install-include: config-install-include oficonv-install-include ofstd-install-include oflog-install-include dcmdata-install-include dcmimgle-install-include dcmimage-install-include dcmjpeg-install-include dcmjpls-install-include dcmtls-install-include dcmnet-install-include dcmsr-install-include dcmsign-install-include dcmwlm-install-include dcmqrdb-install-include dcmrt-install-include dcmiod-install-include dcmpstat-install-include dcmfg-install-include dcmseg-install-include dcmtract-install-include dcmpmap-install-include dcmect-install-include dcmapps-install-include
-install-support: config-install-support oficonv-install-support ofstd-install-support oflog-install-support dcmdata-install-support dcmiod-install-support dcmfg-install-support dcmseg-install-support dcmimgle-install-support dcmimage-install-support dcmjpeg-install-support dcmjpls-install-support dcmtls-install-support dcmnet-install-support dcmsr-install-support dcmsign-install-support dcmwlm-install-support dcmqrdb-install-support dcmpstat-install-support dcmrt-install-support dcmtract-install-support dcmpmap-install-support dcmect-install-support dcmapps-install-support
+install-support: config-install-support oficonv-install-support ofstd-install-support oflog-install-support dcmdata-install-support dcmimgle-install-support dcmimage-install-support dcmjpeg-install-support dcmjpls-install-support dcmtls-install-support dcmnet-install-support dcmsr-install-support dcmsign-install-support dcmwlm-install-support dcmqrdb-install-support dcmrt-install-support dcmiod-install-support dcmpstat-install-support dcmfg-install-support dcmseg-install-support dcmtract-install-support dcmpmap-install-support dcmect-install-support dcmapps-install-support
check: tests-all
$(MAKE) -s check-nosilent
-check-nosilent: config-check oficonv-check ofstd-check oflog-check dcmdata-check dcmiod-check dcmfg-check dcmseg-check dcmimgle-check dcmimage-check dcmjpeg-check dcmjpls-check dcmtls-check dcmnet-check dcmsr-check dcmsign-check dcmwlm-check dcmqrdb-check dcmpstat-check dcmrt-check dcmtract-check dcmpmap-check dcmect-check dcmapps-check
+check-nosilent: config-check oficonv-check ofstd-check oflog-check dcmdata-check dcmimgle-check dcmimage-check dcmjpeg-check dcmjpls-check dcmtls-check dcmnet-check dcmsr-check dcmsign-check dcmwlm-check dcmqrdb-check dcmrt-check dcmiod-check dcmpstat-check dcmfg-check dcmseg-check dcmtract-check dcmpmap-check dcmect-check dcmapps-check
check-exhaustive: tests-all
$(MAKE) -s check-nosilent-exhaustive
-check-nosilent-exhaustive: config-check-exhaustive oficonv-check-exhaustive ofstd-check-exhaustive oflog-check-exhaustive dcmdata-check-exhaustive dcmiod-check-exhaustive dcmfg-check-exhaustive dcmseg-check-exhaustive dcmimgle-check-exhaustive dcmimage-check-exhaustive dcmjpeg-check-exhaustive dcmjpls-check-exhaustive dcmtls-check-exhaustive dcmnet-check-exhaustive dcmsr-check-exhaustive dcmsign-check-exhaustive dcmwlm-check-exhaustive dcmqrdb-check-exhaustive dcmpstat-check-exhaustive dcmrt-check-exhaustive dcmtract-check-exhaustive dcmpmap-check-exhaustive dcmect-check-exhaustive dcmapps-check-exhaustive
+check-nosilent-exhaustive: config-check-exhaustive oficonv-check-exhaustive ofstd-check-exhaustive oflog-check-exhaustive dcmdata-check-exhaustive dcmimgle-check-exhaustive dcmimage-check-exhaustive dcmjpeg-check-exhaustive dcmjpls-check-exhaustive dcmtls-check-exhaustive dcmnet-check-exhaustive dcmsr-check-exhaustive dcmsign-check-exhaustive dcmwlm-check-exhaustive dcmqrdb-check-exhaustive dcmrt-check-exhaustive dcmiod-check-exhaustive dcmpstat-check-exhaustive dcmfg-check-exhaustive dcmseg-check-exhaustive dcmtract-check-exhaustive dcmpmap-check-exhaustive dcmect-check-exhaustive dcmapps-check-exhaustive
dcmtk-install-doc:
$(configdir)/mkinstalldirs $(DESTDIR)$(docdir)
@echo ""
@echo "The following modules are available:"
@echo ""
- @echo "oficonv ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmtract dcmpmap dcmect dcmapps"
+ @echo "oficonv ofstd oflog dcmdata dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmrt dcmiod dcmpstat dcmfg dcmseg dcmtract dcmpmap dcmect dcmapps"
config-all:
(cd config && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
dcmdata-check-exhaustive:
(cd dcmdata && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
-dcmiod-all:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
-
-dcmiod-libsrc-all:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
-
-dcmiod-tests-all:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
-
-dcmiod-install:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
-
-dcmiod-install-bin:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
-
-dcmiod-install-doc:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
-
-dcmiod-install-data:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
-
-dcmiod-install-etc:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
-
-dcmiod-install-lib:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
-
-dcmiod-install-include:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
-
-dcmiod-install-support:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
-
-dcmiod-check:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
-
-dcmiod-check-exhaustive:
- (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
-
-dcmfg-all:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
-
-dcmfg-libsrc-all:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
-
-dcmfg-tests-all:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
-
-dcmfg-install:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
-
-dcmfg-install-bin:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
-
-dcmfg-install-doc:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
-
-dcmfg-install-data:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
-
-dcmfg-install-etc:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
-
-dcmfg-install-lib:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
-
-dcmfg-install-include:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
-
-dcmfg-install-support:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
-
-dcmfg-check:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
-
-dcmfg-check-exhaustive:
- (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
-
-dcmseg-all:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
-
-dcmseg-libsrc-all:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
-
-dcmseg-tests-all:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
-
-dcmseg-install:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
-
-dcmseg-install-bin:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
-
-dcmseg-install-doc:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
-
-dcmseg-install-data:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
-
-dcmseg-install-etc:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
-
-dcmseg-install-lib:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
-
-dcmseg-install-include:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
-
-dcmseg-install-support:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
-
-dcmseg-check:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
-
-dcmseg-check-exhaustive:
- (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
-
dcmimgle-all:
(cd dcmimgle && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
dcmqrdb-check-exhaustive:
(cd dcmqrdb && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
+dcmrt-all:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
+
+dcmrt-libsrc-all:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
+
+dcmrt-tests-all:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
+
+dcmrt-install:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
+
+dcmrt-install-bin:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
+
+dcmrt-install-doc:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
+
+dcmrt-install-data:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
+
+dcmrt-install-etc:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
+
+dcmrt-install-lib:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
+
+dcmrt-install-include:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
+
+dcmrt-install-support:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
+
+dcmrt-check:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
+
+dcmrt-check-exhaustive:
+ (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
+
+dcmiod-all:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
+
+dcmiod-libsrc-all:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
+
+dcmiod-tests-all:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
+
+dcmiod-install:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
+
+dcmiod-install-bin:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
+
+dcmiod-install-doc:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
+
+dcmiod-install-data:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
+
+dcmiod-install-etc:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
+
+dcmiod-install-lib:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
+
+dcmiod-install-include:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
+
+dcmiod-install-support:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
+
+dcmiod-check:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
+
+dcmiod-check-exhaustive:
+ (cd dcmiod && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
+
dcmpstat-all:
(cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
dcmpstat-check-exhaustive:
(cd dcmpstat && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
-dcmrt-all:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
+dcmfg-all:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
-dcmrt-libsrc-all:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
+dcmfg-libsrc-all:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
-dcmrt-tests-all:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
+dcmfg-tests-all:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
-dcmrt-install:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
+dcmfg-install:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
-dcmrt-install-bin:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
+dcmfg-install-bin:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
-dcmrt-install-doc:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
+dcmfg-install-doc:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
-dcmrt-install-data:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
+dcmfg-install-data:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
-dcmrt-install-etc:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
+dcmfg-install-etc:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
-dcmrt-install-lib:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
+dcmfg-install-lib:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
-dcmrt-install-include:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
+dcmfg-install-include:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
-dcmrt-install-support:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
+dcmfg-install-support:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
-dcmrt-check:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
+dcmfg-check:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
-dcmrt-check-exhaustive:
- (cd dcmrt && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
+dcmfg-check-exhaustive:
+ (cd dcmfg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
+
+dcmseg-all:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
+
+dcmseg-libsrc-all:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" libsrc-all)
+
+dcmseg-tests-all:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" tests-all)
+
+dcmseg-install:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install)
+
+dcmseg-install-bin:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-bin)
+
+dcmseg-install-doc:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-doc)
+
+dcmseg-install-data:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-data)
+
+dcmseg-install-etc:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-etc)
+
+dcmseg-install-lib:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-lib)
+
+dcmseg-install-include:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-include)
+
+dcmseg-install-support:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" install-support)
+
+dcmseg-check:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check)
+
+dcmseg-check-exhaustive:
+ (cd dcmseg && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" check-exhaustive)
dcmtract-all:
(cd dcmtract && $(MAKE) ARCH="$(ARCH)" DESTDIR="$(DESTDIR)" all)
(cd ofstd && $(MAKE) dependencies)
(cd oflog && $(MAKE) dependencies)
(cd dcmdata && $(MAKE) dependencies)
- (cd dcmiod && $(MAKE) dependencies)
- (cd dcmfg && $(MAKE) dependencies)
- (cd dcmseg && $(MAKE) dependencies)
(cd dcmimgle && $(MAKE) dependencies)
(cd dcmimage && $(MAKE) dependencies)
(cd dcmjpeg && $(MAKE) dependencies)
(cd dcmsign && $(MAKE) dependencies)
(cd dcmwlm && $(MAKE) dependencies)
(cd dcmqrdb && $(MAKE) dependencies)
- (cd dcmpstat && $(MAKE) dependencies)
(cd dcmrt && $(MAKE) dependencies)
+ (cd dcmiod && $(MAKE) dependencies)
+ (cd dcmpstat && $(MAKE) dependencies)
+ (cd dcmfg && $(MAKE) dependencies)
+ (cd dcmseg && $(MAKE) dependencies)
(cd dcmtract && $(MAKE) dependencies)
(cd dcmpmap && $(MAKE) dependencies)
(cd dcmect && $(MAKE) dependencies)
(cd ofstd && $(MAKE) clean)
(cd oflog && $(MAKE) clean)
(cd dcmdata && $(MAKE) clean)
- (cd dcmiod && $(MAKE) clean)
- (cd dcmfg && $(MAKE) clean)
- (cd dcmseg && $(MAKE) clean)
(cd dcmimgle && $(MAKE) clean)
(cd dcmimage && $(MAKE) clean)
(cd dcmjpeg && $(MAKE) clean)
(cd dcmsign && $(MAKE) clean)
(cd dcmwlm && $(MAKE) clean)
(cd dcmqrdb && $(MAKE) clean)
- (cd dcmpstat && $(MAKE) clean)
(cd dcmrt && $(MAKE) clean)
+ (cd dcmiod && $(MAKE) clean)
+ (cd dcmpstat && $(MAKE) clean)
+ (cd dcmfg && $(MAKE) clean)
+ (cd dcmseg && $(MAKE) clean)
(cd dcmtract && $(MAKE) clean)
(cd dcmpmap && $(MAKE) clean)
(cd dcmect && $(MAKE) clean)
(cd ofstd && $(MAKE) distclean)
(cd oflog && $(MAKE) distclean)
(cd dcmdata && $(MAKE) distclean)
- (cd dcmiod && $(MAKE) distclean)
- (cd dcmfg && $(MAKE) distclean)
- (cd dcmseg && $(MAKE) distclean)
(cd dcmimgle && $(MAKE) distclean)
(cd dcmimage && $(MAKE) distclean)
(cd dcmjpeg && $(MAKE) distclean)
(cd dcmsign && $(MAKE) distclean)
(cd dcmwlm && $(MAKE) distclean)
(cd dcmqrdb && $(MAKE) distclean)
- (cd dcmpstat && $(MAKE) distclean)
(cd dcmrt && $(MAKE) distclean)
+ (cd dcmiod && $(MAKE) distclean)
+ (cd dcmpstat && $(MAKE) distclean)
+ (cd dcmfg && $(MAKE) distclean)
+ (cd dcmseg && $(MAKE) distclean)
(cd dcmtract && $(MAKE) distclean)
(cd dcmpmap && $(MAKE) distclean)
(cd dcmect && $(MAKE) distclean)
rm -f conftest*])
-dnl AC_CHECK_STD_NAMESPACE checks if the C++-Compiler supports the
-dnl standard name space.
-dnl
-dnl AC_CHECK_STD_NAMESPACE
-AC_DEFUN(AC_CHECK_STD_NAMESPACE,
-[AC_MSG_CHECKING([for C++ standard namespace])
-AH_TEMPLATE(HAVE_STD_NAMESPACE, [Define if ANSI standard C++ includes use std namespace.])
-AC_CACHE_VAL(ac_cv_check_std_namespace,
-[AC_TRY_COMPILE_AND_LINK([
-#include <iostream>
-using namespace std;
-],[
- cout << "Hello World" << endl;
-], eval "ac_cv_check_std_namespace=yes", eval "ac_cv_check_std_namespace=no")dnl
-])dnl
-if eval "test \"`echo '$ac_cv_check_std_namespace'`\" = yes"; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_STD_NAMESPACE)
-else
- AC_MSG_RESULT(no)
-fi
-])
-
-
dnl AC_CHECK_GNU_LIBTOOL checks whether libtool is GNU libtool.
dnl This macro requires that 'libtool' exists in the current path,
dnl i.e. AC_CHECK_PROGS(LIBTOOL, libtool, :) should be executed and evaluated
])
-dnl AC_CHECK_INTP_ACCEPT checks if the prototype for accept()
-dnl specifies arguments 2-4 to be int* instead of size_t *.
-dnl
-dnl AC_CHECK_INTP_ACCEPT(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND])
-AC_DEFUN(AC_CHECK_INTP_ACCEPT,
-[AC_MSG_CHECKING([ifelse([$1], , [if accept() needs int* parameters],
-[if accept() needs int* parameters (in $1)])])
-AH_TEMPLATE(HAVE_INTP_ACCEPT, [Define if your system declares argument 3 of accept()
- as int * instead of size_t * or socklen_t *.])
-ifelse([$1], , [ac_includes=""
-],
-[ac_includes=""
-for ac_header in $1
-do
- ac_includes="$ac_includes
-#include<$ac_header>"
-done])
-AC_CACHE_VAL(ac_cv_prototype_intp_accept,
-[AC_TRY_COMPILE(
-[#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-]
-,
-[
- int i;
- struct sockaddr *addr;
- size_t addrlen;
-
- addr = 0;
- addrlen = 0;
- i = accept(1, addr, &addrlen);
-],
-eval "ac_cv_prototype_intp_accept=no",
-[AC_TRY_COMPILE(
-[#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-]
-,
-[
- int i;
- struct sockaddr *addr;
- int addrlen;
-
- addr = 0;
- addrlen = 0;
- i = accept(1, addr, &addrlen);
-],
-eval "ac_cv_prototype_intp_accept=yes", eval "ac_cv_prototype_intp_accept=no")])])
-if eval "test \"`echo $ac_cv_prototype_intp_accept`\" = yes"; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_INTP_ACCEPT)
- ifelse([$2], , :, [$2])
-else
- AC_MSG_RESULT(no)
- ifelse([$3], , , [$3])
-fi
-])
-
-
dnl AC_CHECK_PTHREAD_OPTION checks whether the compiler requires the
dnl -pthread option to correctly link code containing posix thread calls.
dnl This is true for example on FreeBSD.
])
-dnl AC_CHECK_INTP_GETSOCKOPT checks if the prototype for getsockopt()
-dnl specifies arguments 5 to be int* instead of size_t *.
-dnl
-dnl AC_CHECK_INTP_GETSOCKOPT(HEADER-FILE..., ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND])
-AC_DEFUN(AC_CHECK_INTP_GETSOCKOPT,
-[AC_MSG_CHECKING([ifelse([$1], , [if getsockopt() needs int* parameters],
-[if getsockopt() needs int* parameters (in $1)])])
-AH_TEMPLATE(HAVE_INTP_GETSOCKOPT, [Define if your system declares argument 5 of getsockopt()
- as int * instead of size_t * or socklen_t.])
-ifelse([$1], , [ac_includes=""
-],
-[ac_includes=""
-for ac_header in $1
-do
- ac_includes="$ac_includes
-#include<$ac_header>"
-done])
-AC_CACHE_VAL(ac_cv_prototype_intp_getsockopt,
-[AC_TRY_COMPILE(
-[#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-]
-,
-[
- int i;
- size_t optlen;
- i = getsockopt(0, 0, 0, 0, &optlen);
-],
-eval "ac_cv_prototype_intp_getsockopt=no",
-[AC_TRY_COMPILE(
-[#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-]
-,
-[
- int i;
- int optlen;
- i = getsockopt(0, 0, 0, 0, &optlen);
-],
-eval "ac_cv_prototype_intp_getsockopt=yes", eval "ac_cv_prototype_intp_getsockopt=no")])])
-if eval "test \"`echo $ac_cv_prototype_intp_getsockopt`\" = yes"; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_INTP_GETSOCKOPT)
- ifelse([$2], , :, [$2])
-else
- AC_MSG_RESULT(no)
- ifelse([$3], , , [$3])
-fi
-])
-
-
-dnl AC_CXX_STD_NOTHROW checks if the compiler supports non-throwing new using
-dnl std::nothrow.
-dnl
-AC_DEFUN([AC_CXX_STD_NOTHROW],
-[AH_TEMPLATE(HAVE_STD__NOTHROW, [Define if the compiler supports std::nothrow.])
-AC_CACHE_CHECK(whether the compiler supports std::nothrow,
-ac_cv_cxx_std_nothrow,
-[AC_LANG_SAVE
- AC_LANG_CPLUSPLUS
- AC_TRY_COMPILE([#include <new>],[int *i = new (std::nothrow) int],
- ac_cv_cxx_std_nothrow=yes, ac_cv_cxx_std_nothrow=no)
- AC_LANG_RESTORE
-])
-if test "$ac_cv_cxx_std_nothrow" = yes; then
- AC_DEFINE(HAVE_STD__NOTHROW)
-fi
-])
-
-
-dnl AC_CXX_NOTHROW_DELETE checks if the compiler supports non-throwing delete using
-dnl std::nothrow.
-dnl
-AC_DEFUN([AC_CXX_NOTHROW_DELETE],
-[AH_TEMPLATE(HAVE_NOTHROW_DELETE, [Define if the compiler supports operator delete (std::nothrow).])
-AC_CACHE_CHECK(whether the compiler supports operator delete (std::nothrow),
-ac_cv_cxx_nothrow_delete,
-[AC_LANG_SAVE
- AC_LANG_CPLUSPLUS
- AC_TRY_COMPILE([#include <new>],[int *i = new (std::nothrow) int; operator delete (i,std::nothrow)],
- ac_cv_cxx_nothrow_delete=yes, ac_cv_cxx_nothrow_delete=no)
- AC_LANG_RESTORE
-])
-if test "$ac_cv_cxx_nothrow_delete" = yes; then
- AC_DEFINE(HAVE_NOTHROW_DELETE)
-fi
-])
-
-
dnl AC_CXX_STATIC_ASSERT checks if the compiler supports static_assert.
dnl
AC_DEFUN([AC_CXX_STATIC_ASSERT],
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for dcmtk 3.6.9.
+# Generated by GNU Autoconf 2.69 for dcmtk 3.7.0.
#
# Report bugs to <bugs@dcmtk.org>.
#
# Identity of this package.
PACKAGE_NAME='dcmtk'
-PACKAGE_TARNAME='dcmtk-3.6.9'
-PACKAGE_VERSION='3.6.9'
-PACKAGE_STRING='dcmtk 3.6.9'
+PACKAGE_TARNAME='dcmtk-3.7.0'
+PACKAGE_VERSION='3.7.0'
+PACKAGE_STRING='dcmtk 3.7.0'
PACKAGE_BUGREPORT='bugs@dcmtk.org'
PACKAGE_URL='https://www.dcmtk.org/'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
-datadir='${datarootdir}/dcmtk-3.6.9'
-sysconfdir='${prefix}/etc/dcmtk-3.6.9'
+datadir='${datarootdir}/dcmtk-3.7.0'
+sysconfdir='${prefix}/etc/dcmtk-3.7.0'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/dcmtk-3.6.9'
+docdir='${datarootdir}/doc/dcmtk-3.7.0'
infodir='${datarootdir}/info'
htmldir='${docdir}/html'
dvidir='${docdir}'
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures dcmtk 3.6.9 to adapt to many kinds of systems.
+\`configure' configures dcmtk 3.7.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk-3.6.9]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk-3.7.0]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
- --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk-3.6.9]
+ --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk-3.7.0]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk-3.6.9]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk-3.7.0]
--htmldir=DIR html documentation [DOCDIR/html]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of dcmtk 3.6.9:";;
+ short | recursive ) echo "Configuration of dcmtk 3.7.0:";;
esac
cat <<\_ACEOF
--without-openjpeg don't include OpenJPEG support
--with-libsndfileinc=DIR
location of libsndfile includes and libraries
- --with-libsndfile include libsndfile support (default: auto)
+ --with-libsndfile include libsndfile support (default: no)
--without-libsndfile don't include libsndfile support
--with-libiconvinc=DIR location of libiconv includes and libraries
--with-libiconv include libiconv support (default: auto)
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-dcmtk configure 3.6.9
+dcmtk configure 3.7.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by dcmtk $as_me 3.6.9, which was
+It was created by dcmtk $as_me 3.7.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
-PACKAGE_VERSION_NUMBER=368
-PACKAGE_VERSION_SUFFIX="+"
-PACKAGE_DATE="DEV"
+PACKAGE_VERSION_NUMBER=370
+PACKAGE_VERSION_SUFFIX=""
+PACKAGE_DATE="2025-12-15"
cat >>confdefs.h <<_ACEOF
#define PACKAGE_VERSION_NUMBER ${PACKAGE_VERSION_NUMBER}
fi
-ac_fn_c_check_type "$LINENO" "sigjmp_buf" "ac_cv_type_sigjmp_buf" "#include <setjmp.h>
-"
-if test "x$ac_cv_type_sigjmp_buf" = xyes; then :
-
-cat >>confdefs.h <<_ACEOF
-#define HAVE_SIGJMP_BUF 1
-_ACEOF
-
-
-fi
-
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5
$as_echo_n "checking for working memcmp... " >&6; }
fi
done
-for ac_func in itoa atoll
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-for ac_func in bcmp
-do :
- ac_fn_c_check_func "$LINENO" "bcmp" "ac_cv_func_bcmp"
-if test "x$ac_cv_func_bcmp" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_BCMP 1
-_ACEOF
-
-fi
-done
-
-for ac_func in getpid mktemp mkstemp
+for ac_func in atoll
do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ ac_fn_c_check_func "$LINENO" "atoll" "ac_cv_func_atoll"
+if test "x$ac_cv_func_atoll" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define HAVE_ATOLL 1
_ACEOF
fi
done
-for ac_func in stat
+for ac_func in mkstemp
do :
- ac_fn_c_check_func "$LINENO" "stat" "ac_cv_func_stat"
-if test "x$ac_cv_func_stat" = xyes; then :
+ ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
+if test "x$ac_cv_func_mkstemp" = xyes; then :
cat >>confdefs.h <<_ACEOF
-#define HAVE_STAT 1
+#define HAVE_MKSTEMP 1
_ACEOF
fi
fi
done
-for ac_func in strdup index rindex access
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
for ac_func in uname cuserid getlogin getlogin_r
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
fi
done
-for ac_func in listen
-do :
- ac_fn_c_check_func "$LINENO" "listen" "ac_cv_func_listen"
-if test "x$ac_cv_func_listen" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LISTEN 1
-_ACEOF
-
-fi
-done
-
for ac_func in gethostbyname_r
do :
ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r"
fi
done
-for ac_func in getrusage
-do :
- ac_fn_c_check_func "$LINENO" "getrusage" "ac_cv_func_getrusage"
-if test "x$ac_cv_func_getrusage" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETRUSAGE 1
-_ACEOF
-
-fi
-done
-
for ac_func in gettimeofday
do :
ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday"
fi
done
-for ac_func in vsnprintf
-do :
- ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf"
-if test "x$ac_cv_func_vsnprintf" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_VSNPRINTF 1
-_ACEOF
-
-fi
-done
-
for ac_func in popen pclose
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-
-
for ac_func in ftime gmtime_r localtime_r lstat nanosleep fcntl
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5
-$as_echo_n "checking for socklen_t... " >&6; }
-if ${ac_cv_type_socklen_t+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
- #include <sys/socket.h>
-int
-main ()
-{
-socklen_t len = 42; return 0;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_type_socklen_t=yes
-else
- ac_cv_type_socklen_t=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_socklen_t" >&5
-$as_echo "$ac_cv_type_socklen_t" >&6; }
- if test $ac_cv_type_socklen_t != yes; then
- $as_echo "#define socklen_t int" >>confdefs.h
-
- fi
-
-
-
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <errno.h>
-SAVELIBS="$LIBS"
-LIBS="$LIBS -lm"
-for ac_func in finite
-do :
- ac_fn_c_check_func "$LINENO" "finite" "ac_cv_func_finite"
-if test "x$ac_cv_func_finite" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_FINITE 1
-_ACEOF
-
-fi
-done
-
-LIBS="$SAVELIBS"
-
-
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports std::nothrow" >&5
-$as_echo_n "checking whether the compiler supports std::nothrow... " >&6; }
-if ${ac_cv_cxx_std_nothrow+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <new>
-int
-main ()
-{
-int *i = new (std::nothrow) int
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- ac_cv_cxx_std_nothrow=yes
-else
- ac_cv_cxx_std_nothrow=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_std_nothrow" >&5
-$as_echo "$ac_cv_cxx_std_nothrow" >&6; }
-if test "$ac_cv_cxx_std_nothrow" = yes; then
- $as_echo "#define HAVE_STD__NOTHROW 1" >>confdefs.h
-
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports operator delete (std::nothrow)" >&5
-$as_echo_n "checking whether the compiler supports operator delete (std::nothrow)... " >&6; }
-if ${ac_cv_cxx_nothrow_delete+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <new>
-int
-main ()
-{
-int *i = new (std::nothrow) int; operator delete (i,std::nothrow)
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- ac_cv_cxx_nothrow_delete=yes
-else
- ac_cv_cxx_nothrow_delete=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_nothrow_delete" >&5
-$as_echo "$ac_cv_cxx_nothrow_delete" >&6; }
-if test "$ac_cv_cxx_nothrow_delete" = yes; then
- $as_echo "#define HAVE_NOTHROW_DELETE 1" >>confdefs.h
-
-fi
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports static_assert" >&5
-$as_echo_n "checking whether the compiler supports static_assert... " >&6; }
-if ${ac_cv_cxx_static_assert+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <cassert>
-int
-main ()
-{
-static_assert(true, "good")
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- ac_cv_cxx_static_assert=yes
-else
- ac_cv_cxx_static_assert=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_static_assert" >&5
-$as_echo "$ac_cv_cxx_static_assert" >&6; }
-if test "$ac_cv_cxx_static_assert" = yes; then
- $as_echo "#define HAVE_STATIC_ASSERT 1" >>confdefs.h
-
-fi
-
-
-
DEBUG="-DNDEBUG"
DEBUGCXXFLAGS=
DEBUGCFLAGS=
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -lg++" >&5
$as_echo_n "checking for -lg++... " >&6; }
if ${ac_cv_lib_gxx+:} false; then :
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5
-$as_echo_n "checking for main in -lnsl... " >&6; }
-if ${ac_cv_lib_nsl_main+:} false; then :
+OPENSSLLIBS=""
+OPENJPEGLIBS=""
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5
+$as_echo_n "checking for main in -ldl... " >&6; }
+if ${ac_cv_lib_dl_main+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnsl $LIBS"
+LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_nsl_main=yes
+ ac_cv_lib_dl_main=yes
else
- ac_cv_lib_nsl_main=no
+ ac_cv_lib_dl_main=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5
-$as_echo "$ac_cv_lib_nsl_main" >&6; }
-if test "x$ac_cv_lib_nsl_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNSL 1
-_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5
+$as_echo "$ac_cv_lib_dl_main" >&6; }
+if test "x$ac_cv_lib_dl_main" = xyes; then :
- LIBS="-lnsl $LIBS"
+OPENSSLLIBS="-ldl"
+OPENJPEGLIBS="-ldl"
fi
-if test $ac_cv_lib_nsl_main = no ; then
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5
-$as_echo_n "checking for gethostbyname in -lnsl... " >&6; }
-if ${ac_cv_lib_nsl_gethostbyname+:} false; then :
+if test $ac_cv_lib_dl_main = no ; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnsl $LIBS"
+LIBS="-ldl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __cplusplus
extern "C"
#endif
-char gethostbyname ();
+char dlopen ();
int
main ()
{
-return gethostbyname ();
+return dlopen ();
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_nsl_gethostbyname=yes
+ ac_cv_lib_dl_dlopen=yes
else
- ac_cv_lib_nsl_gethostbyname=no
+ ac_cv_lib_dl_dlopen=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5
-$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; }
-if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNSL 1
-_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
- LIBS="-lnsl $LIBS"
+OPENSSLLIBS="-ldl"
+OPENJPEGLIBS="-ldl"
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5
-$as_echo_n "checking for main in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_main+:} false; then :
+
+MATHLIBS=""
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5
+$as_echo_n "checking for main in -lm... " >&6; }
+if ${ac_cv_lib_m_main+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket $LIBS"
+LIBS="-lm $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_socket_main=yes
+ ac_cv_lib_m_main=yes
else
- ac_cv_lib_socket_main=no
+ ac_cv_lib_m_main=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5
-$as_echo "$ac_cv_lib_socket_main" >&6; }
-if test "x$ac_cv_lib_socket_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSOCKET 1
-_ACEOF
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5
+$as_echo "$ac_cv_lib_m_main" >&6; }
+if test "x$ac_cv_lib_m_main" = xyes; then :
- LIBS="-lsocket $LIBS"
+MATHLIBS="-lm"
fi
-if test $ac_cv_lib_socket_main = no ; then
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
-$as_echo_n "checking for socket in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_socket+:} false; then :
+if test $ac_cv_lib_m_main = no ; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
+$as_echo_n "checking for sin in -lm... " >&6; }
+if ${ac_cv_lib_m_sin+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket $LIBS"
+LIBS="-lm $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifdef __cplusplus
extern "C"
#endif
-char socket ();
+char sin ();
int
main ()
{
-return socket ();
+return sin ();
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_socket_socket=yes
+ ac_cv_lib_m_sin=yes
else
- ac_cv_lib_socket_socket=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
-$as_echo "$ac_cv_lib_socket_socket" >&6; }
-if test "x$ac_cv_lib_socket_socket" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSOCKET 1
-_ACEOF
-
- LIBS="-lsocket $LIBS"
-
-fi
-
-fi
-
-OPENSSLLIBS=""
-OPENJPEGLIBS=""
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5
-$as_echo_n "checking for main in -ldl... " >&6; }
-if ${ac_cv_lib_dl_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-return main ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_dl_main=yes
-else
- ac_cv_lib_dl_main=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5
-$as_echo "$ac_cv_lib_dl_main" >&6; }
-if test "x$ac_cv_lib_dl_main" = xyes; then :
-
-OPENSSLLIBS="-ldl"
-OPENJPEGLIBS="-ldl"
-
-fi
-
-if test $ac_cv_lib_dl_main = no ; then
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
-$as_echo_n "checking for dlopen in -ldl... " >&6; }
-if ${ac_cv_lib_dl_dlopen+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ldl $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen ();
-int
-main ()
-{
-return dlopen ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_dl_dlopen=yes
-else
- ac_cv_lib_dl_dlopen=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
-$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
-if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
-
-OPENSSLLIBS="-ldl"
-OPENJPEGLIBS="-ldl"
-
-fi
-
-fi
-
-MATHLIBS=""
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5
-$as_echo_n "checking for main in -lm... " >&6; }
-if ${ac_cv_lib_m_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lm $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
-int
-main ()
-{
-return main ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_m_main=yes
-else
- ac_cv_lib_m_main=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5
-$as_echo "$ac_cv_lib_m_main" >&6; }
-if test "x$ac_cv_lib_m_main" = xyes; then :
-
-MATHLIBS="-lm"
-
-fi
-
-if test $ac_cv_lib_m_main = no ; then
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
-$as_echo_n "checking for sin in -lm... " >&6; }
-if ${ac_cv_lib_m_sin+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lm $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char sin ();
-int
-main ()
-{
-return sin ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- ac_cv_lib_m_sin=yes
-else
- ac_cv_lib_m_sin=no
+ ac_cv_lib_m_sin=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
done
-for ac_header in fcntl.h
-do :
- ac_fn_cxx_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default"
-if test "x$ac_cv_header_fcntl_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_FCNTL_H 1
-_ACEOF
-
-fi
-
-done
-
for ac_header in fnmatch.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "fnmatch.h" "ac_cv_header_fnmatch_h" "$ac_includes_default"
done
-for ac_header in malloc.h
-do :
- ac_fn_cxx_check_header_mongrel "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default"
-if test "x$ac_cv_header_malloc_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_MALLOC_H 1
-_ACEOF
-
-fi
-
-done
-
for ac_header in mqueue.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "mqueue.h" "ac_cv_header_mqueue_h" "$ac_includes_default"
done
-for ac_header in stdint.h
-do :
- ac_fn_cxx_check_header_mongrel "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default"
-if test "x$ac_cv_header_stdint_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_STDINT_H 1
-_ACEOF
-
-fi
-
-done
-
for ac_header in strings.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "strings.h" "ac_cv_header_strings_h" "$ac_includes_default"
done
-for ac_header in sys/errno.h
-do :
- ac_fn_cxx_check_header_mongrel "$LINENO" "sys/errno.h" "ac_cv_header_sys_errno_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_errno_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_ERRNO_H 1
-_ACEOF
-
-fi
-
-done
-
for ac_header in sys/file.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "sys/file.h" "ac_cv_header_sys_file_h" "$ac_includes_default"
done
-for ac_header in sys/stat.h
-do :
- ac_fn_cxx_check_header_mongrel "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_stat_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_STAT_H 1
-_ACEOF
-
-fi
-
-done
-
for ac_header in sys/syscall.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "sys/syscall.h" "ac_cv_header_sys_syscall_h" "$ac_includes_default"
done
-for ac_header in sys/types.h
-do :
- ac_fn_cxx_check_header_mongrel "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_types_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SYS_TYPES_H 1
-_ACEOF
-
-fi
-
-done
-
for ac_header in sys/un.h
do :
ac_fn_cxx_check_header_mongrel "$LINENO" "sys/un.h" "ac_cv_header_sys_un_h" "$ac_includes_default"
fi
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
-$as_echo_n "checking size of short... " >&6; }
-if ${ac_cv_sizeof_short+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type_short" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (short)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_short=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
-$as_echo "$ac_cv_sizeof_short" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_SHORT $ac_cv_sizeof_short
-_ACEOF
-
-
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of float" >&5
-$as_echo_n "checking size of float... " >&6; }
-if ${ac_cv_sizeof_float+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+$as_echo_n "checking size of void *... " >&6; }
+if ${ac_cv_sizeof_void_p+:} false; then :
$as_echo_n "(cached) " >&6
else
- if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (float))" "ac_cv_sizeof_float" "$ac_includes_default"; then :
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
else
- if test "$ac_cv_type_float" = yes; then
+ if test "$ac_cv_type_void_p" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (float)
+as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
- ac_cv_sizeof_float=0
+ ac_cv_sizeof_void_p=0
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_float" >&5
-$as_echo "$ac_cv_sizeof_float" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+$as_echo "$ac_cv_sizeof_void_p" >&6; }
cat >>confdefs.h <<_ACEOF
-#define SIZEOF_FLOAT $ac_cv_sizeof_float
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
_ACEOF
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of double" >&5
-$as_echo_n "checking size of double... " >&6; }
-if ${ac_cv_sizeof_double+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (double))" "ac_cv_sizeof_double" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type_double" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (double)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_double=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_double" >&5
-$as_echo "$ac_cv_sizeof_double" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_DOUBLE $ac_cv_sizeof_double
-_ACEOF
-
-
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
- if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (void *)
-See \`config.log' for more details" "$LINENO" 5; }
- else
- ac_cv_sizeof_void_p=0
- fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
-$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
-if ${ac_cv_struct_tm+:} false; then :
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
+$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
+if ${ac_cv_struct_tm+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for feenableexcept (in fenv.h)" >&5
-$as_echo_n "checking prototype for feenableexcept (in fenv.h)... " >&6; }
-
-:
-ac_includes=""
-for ac_header in fenv.h
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo feenableexcept | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct feenableexcept(dummyStruct);
-
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
-else
- eval "ac_cv_prototype_$tmp_save_1=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_FEENABLEEXCEPT 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for _stricmp (in string.h)" >&5
$as_echo_n "checking prototype for _stricmp (in string.h)... " >&6; }
$as_echo "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if accept() needs int* parameters (in sys/types.h sys/socket.h)" >&5
-$as_echo_n "checking if accept() needs int* parameters (in sys/types.h sys/socket.h)... " >&6; }
-
-ac_includes=""
-for ac_header in sys/types.h sys/socket.h
-do
- ac_includes="$ac_includes
-#include<$ac_header>"
-done
-if ${ac_cv_prototype_intp_accept+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-
-
-int
-main ()
-{
-
- int i;
- struct sockaddr *addr;
- size_t addrlen;
-
- addr = 0;
- addrlen = 0;
- i = accept(1, addr, &addrlen);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_intp_accept=no"
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-
-
-int
-main ()
-{
-
- int i;
- struct sockaddr *addr;
- int addrlen;
-
- addr = 0;
- addrlen = 0;
- i = accept(1, addr, &addrlen);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_intp_accept=yes"
-else
- eval "ac_cv_prototype_intp_accept=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-if eval "test \"`echo $ac_cv_prototype_intp_accept`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_INTP_ACCEPT 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for finite (in math.h)" >&5
-$as_echo_n "checking prototype for finite (in math.h)... " >&6; }
-
-:
-ac_includes=""
-for ac_header in math.h
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo finite | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct finite(dummyStruct);
-
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
-else
- eval "ac_cv_prototype_$tmp_save_1=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_FINITE 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for std::isinf (in cmath)" >&5
-$as_echo_n "checking prototype for std::isinf (in cmath)... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for flock (in sys/file.h)" >&5
+$as_echo_n "checking prototype for flock (in sys/file.h)... " >&6; }
:
ac_includes=""
-for ac_header in cmath
+for ac_header in sys/file.h
do
ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
#include<$ac_header>"
fi
done
-tmp_save_1=`echo std::isinf | tr ' :' '__'`
+tmp_save_1=`echo flock | tr ' :' '__'`
if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
$as_echo_n "(cached) " >&6
else
#ifdef __cplusplus
extern "C"
#endif
-dummyStruct std::isinf(dummyStruct);
+dummyStruct flock(dummyStruct);
int
if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_STD__ISINF 1" >>confdefs.h
+ $as_echo "#define HAVE_PROTOTYPE_FLOCK 1" >>confdefs.h
:
else
$as_echo "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for std::isnan (in cmath)" >&5
-$as_echo_n "checking prototype for std::isnan (in cmath)... " >&6; }
-
-:
-ac_includes=""
-for ac_header in cmath
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo std::isnan | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct std::isnan(dummyStruct);
-
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
-else
- eval "ac_cv_prototype_$tmp_save_1=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_STD__ISNAN 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for flock (in sys/file.h)" >&5
-$as_echo_n "checking prototype for flock (in sys/file.h)... " >&6; }
-
-:
-ac_includes=""
-for ac_header in sys/file.h
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo flock | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct flock(dummyStruct);
-
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
-else
- eval "ac_cv_prototype_$tmp_save_1=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_FLOCK 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostbyname_r (in libc.h unistd.h stdlib.h netdb.h)" >&5
-$as_echo_n "checking prototype for gethostbyname_r (in libc.h unistd.h stdlib.h netdb.h)... " >&6; }
-
-:
-ac_includes=""
-for ac_header in libc.h unistd.h stdlib.h netdb.h
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo gethostbyname_r | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct gethostbyname_r(dummyStruct);
-
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
-else
- eval "ac_cv_prototype_$tmp_save_1=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_GETHOSTBYNAME_R 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostbyaddr_r (in libc.h unistd.h stdlib.h netdb.h)" >&5
-$as_echo_n "checking prototype for gethostbyaddr_r (in libc.h unistd.h stdlib.h netdb.h)... " >&6; }
-
-:
-ac_includes=""
-for ac_header in libc.h unistd.h stdlib.h netdb.h
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo gethostbyaddr_r | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct gethostbyaddr_r(dummyStruct);
-
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
-else
- eval "ac_cv_prototype_$tmp_save_1=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_GETHOSTBYADDR_R 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostid (in libc.h unistd.h stdlib.h netdb.h)" >&5
-$as_echo_n "checking prototype for gethostid (in libc.h unistd.h stdlib.h netdb.h)... " >&6; }
-
-:
-ac_includes=""
-for ac_header in libc.h unistd.h stdlib.h netdb.h
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo gethostid | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
-#ifdef __cplusplus
-}
-#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct gethostid(dummyStruct);
-
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
-else
- eval "ac_cv_prototype_$tmp_save_1=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_GETHOSTID 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for strerror_r (in string.h)" >&5
-$as_echo_n "checking prototype for strerror_r (in string.h)... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostbyname_r (in libc.h unistd.h stdlib.h netdb.h)" >&5
+$as_echo_n "checking prototype for gethostbyname_r (in libc.h unistd.h stdlib.h netdb.h)... " >&6; }
:
ac_includes=""
-for ac_header in string.h
+for ac_header in libc.h unistd.h stdlib.h netdb.h
do
ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
#include<$ac_header>"
fi
done
-tmp_save_1=`echo strerror_r | tr ' :' '__'`
+tmp_save_1=`echo gethostbyname_r | tr ' :' '__'`
if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
$as_echo_n "(cached) " >&6
else
#ifdef __cplusplus
extern "C"
#endif
-dummyStruct strerror_r(dummyStruct);
+dummyStruct gethostbyname_r(dummyStruct);
int
if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_STRERROR_R 1" >>confdefs.h
+ $as_echo "#define HAVE_PROTOTYPE_GETHOSTBYNAME_R 1" >>confdefs.h
:
else
$as_echo "no" >&6; }
fi
-if test $ac_cv_prototype_strerror_r = yes ; then
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if strerror_r() returns a char * (in string.h)" >&5
-$as_echo_n "checking if strerror_r() returns a char * (in string.h)... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostbyaddr_r (in libc.h unistd.h stdlib.h netdb.h)" >&5
+$as_echo_n "checking prototype for gethostbyaddr_r (in libc.h unistd.h stdlib.h netdb.h)... " >&6; }
+:
ac_includes=""
-for ac_header in string.h
+for ac_header in libc.h unistd.h stdlib.h netdb.h
do
- ac_includes="$ac_includes
+ ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
+ ac_includes="$ac_includes
#include<$ac_header>"
+ fi
done
-if ${ac_cv_prototype_charp_strerror_r+:} false; then :
+tmp_save_1=`echo gethostbyaddr_r | tr ' :' '__'`
+if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
}
#endif
+typedef union { int member; } dummyStruct;
+#ifdef __cplusplus
+extern "C"
+#endif
+dummyStruct gethostbyaddr_r(dummyStruct);
int
main ()
{
- char *buf = 0;
- int i = strerror_r(0, buf, 100)
-
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_charp_strerror_r=no"
+ eval "ac_cv_prototype_$tmp_save_1=no"
else
- eval "ac_cv_prototype_charp_strerror_r=yes"
-
+ eval "ac_cv_prototype_$tmp_save_1=yes"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-if eval "test \"`echo $ac_cv_prototype_charp_strerror_r`\" = yes"; then
+if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define HAVE_CHARP_STRERROR_R 1" >>confdefs.h
+ $as_echo "#define HAVE_PROTOTYPE_GETHOSTBYADDR_R 1" >>confdefs.h
:
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
-
fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if getsockopt() needs int* parameters (in sys/types.h sys/socket.h)" >&5
-$as_echo_n "checking if getsockopt() needs int* parameters (in sys/types.h sys/socket.h)... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gethostid (in libc.h unistd.h stdlib.h netdb.h)" >&5
+$as_echo_n "checking prototype for gethostid (in libc.h unistd.h stdlib.h netdb.h)... " >&6; }
+:
ac_includes=""
-for ac_header in sys/types.h sys/socket.h
+for ac_header in libc.h unistd.h stdlib.h netdb.h
do
- ac_includes="$ac_includes
+ ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
+ ac_includes="$ac_includes
#include<$ac_header>"
+ fi
done
-if ${ac_cv_prototype_intp_getsockopt+:} false; then :
+tmp_save_1=`echo gethostid | tr ' :' '__'`
+if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
}
#endif
-
-
-int
-main ()
-{
-
- int i;
- size_t optlen;
- i = getsockopt(0, 0, 0, 0, &optlen);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_intp_getsockopt=no"
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __cplusplus
-extern "C" {
-#endif
-$ac_includes
+typedef union { int member; } dummyStruct;
#ifdef __cplusplus
-}
+extern "C"
#endif
+dummyStruct gethostid(dummyStruct);
int
main ()
{
- int i;
- int optlen;
- i = getsockopt(0, 0, 0, 0, &optlen);
-
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_intp_getsockopt=yes"
+ eval "ac_cv_prototype_$tmp_save_1=no"
else
- eval "ac_cv_prototype_intp_getsockopt=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ eval "ac_cv_prototype_$tmp_save_1=yes"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-
-if eval "test \"`echo $ac_cv_prototype_intp_getsockopt`\" = yes"; then
+if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define HAVE_INTP_GETSOCKOPT 1" >>confdefs.h
+ $as_echo "#define HAVE_PROTOTYPE_GETHOSTID 1" >>confdefs.h
:
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
-
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gettimeofday (in sys/time.h unistd.h)" >&5
-$as_echo_n "checking prototype for gettimeofday (in sys/time.h unistd.h)... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for strerror_r (in string.h)" >&5
+$as_echo_n "checking prototype for strerror_r (in string.h)... " >&6; }
:
ac_includes=""
-for ac_header in sys/time.h unistd.h
+for ac_header in string.h
do
ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
#include<$ac_header>"
fi
done
-tmp_save_1=`echo gettimeofday | tr ' :' '__'`
+tmp_save_1=`echo strerror_r | tr ' :' '__'`
if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
$as_echo_n "(cached) " >&6
else
#ifdef __cplusplus
extern "C"
#endif
-dummyStruct gettimeofday(dummyStruct);
+dummyStruct strerror_r(dummyStruct);
int
if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_GETTIMEOFDAY 1" >>confdefs.h
+ $as_echo "#define HAVE_PROTOTYPE_STRERROR_R 1" >>confdefs.h
:
else
$as_echo "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for mktemp (in libc.h unistd.h stdlib.h)" >&5
-$as_echo_n "checking prototype for mktemp (in libc.h unistd.h stdlib.h)... " >&6; }
+if test $ac_cv_prototype_strerror_r = yes ; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if strerror_r() returns a char * (in string.h)" >&5
+$as_echo_n "checking if strerror_r() returns a char * (in string.h)... " >&6; }
-:
ac_includes=""
-for ac_header in libc.h unistd.h stdlib.h
+for ac_header in string.h
do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
+ ac_includes="$ac_includes
#include<$ac_header>"
- fi
done
-tmp_save_1=`echo mktemp | tr ' :' '__'`
-if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
+if ${ac_cv_prototype_charp_strerror_r+:} false; then :
$as_echo_n "(cached) " >&6
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
}
#endif
-typedef union { int member; } dummyStruct;
-#ifdef __cplusplus
-extern "C"
-#endif
-dummyStruct mktemp(dummyStruct);
int
main ()
{
+ char *buf = 0;
+ int i = strerror_r(0, buf, 100)
+
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_prototype_$tmp_save_1=no"
+ eval "ac_cv_prototype_charp_strerror_r=no"
else
- eval "ac_cv_prototype_$tmp_save_1=yes"
+ eval "ac_cv_prototype_charp_strerror_r=yes"
+
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
-if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
+
+if eval "test \"`echo $ac_cv_prototype_charp_strerror_r`\" = yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_MKTEMP 1" >>confdefs.h
+ $as_echo "#define HAVE_CHARP_STRERROR_R 1" >>confdefs.h
:
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for mkstemp (in libc.h unistd.h stdlib.h)" >&5
-$as_echo_n "checking prototype for mkstemp (in libc.h unistd.h stdlib.h)... " >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking prototype for gettimeofday (in sys/time.h unistd.h)" >&5
+$as_echo_n "checking prototype for gettimeofday (in sys/time.h unistd.h)... " >&6; }
:
ac_includes=""
-for ac_header in libc.h unistd.h stdlib.h
+for ac_header in sys/time.h unistd.h
do
ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
#include<$ac_header>"
fi
done
-tmp_save_1=`echo mkstemp | tr ' :' '__'`
+tmp_save_1=`echo gettimeofday | tr ' :' '__'`
if eval \${ac_cv_prototype_$tmp_save_1+:} false; then :
$as_echo_n "(cached) " >&6
else
#ifdef __cplusplus
extern "C"
#endif
-dummyStruct mkstemp(dummyStruct);
+dummyStruct gettimeofday(dummyStruct);
int
if eval "test \"`echo '$''{'ac_cv_prototype_$tmp_save_1'}'`\" = yes"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_MKSTEMP 1" >>confdefs.h
+ $as_echo "#define HAVE_PROTOTYPE_GETTIMEOFDAY 1" >>confdefs.h
:
else
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ standard namespace" >&5
-$as_echo_n "checking for C++ standard namespace... " >&6; }
-
-if ${ac_cv_check_std_namespace+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_link_o='${CXX-g++} -o conftest $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.o $LIBS 1>&5'
-cat > conftest.$ac_ext <<EOF
-#line 10421 "configure"
-#include "confdefs.h"
-
-#include <iostream>
-using namespace std;
-
-int main() {
-
- cout << "Hello World" << endl;
-
-; return 0; }
-EOF
-if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link_o\""; } >&5
- (eval $ac_link_o) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- rm -rf conftest*
- eval "ac_cv_check_std_namespace=yes"
- else
- echo "configure: failed link was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_check_std_namespace=no"
- fi
-else
- echo "configure: failed compile was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_check_std_namespace=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_check_std_namespace'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_STD_NAMESPACE 1" >>confdefs.h
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::vfprintf (in cstdarg cstdio)" >&5
-$as_echo_n "checking for std::vfprintf (in cstdarg cstdio)... " >&6; }
-
-ac_includes=""
-for ac_header in cstdarg cstdio
-do
- ac_safe=`echo "$ac_header" | sed 'y%./+-%__p_%'`
- if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'}'`\" = yes"; then
- ac_includes="$ac_includes
-#include<$ac_header>"
- fi
-done
-tmp_save_1=`echo std::vfprintf | tr ' :' '__'`
-if eval \${ac_cv_compiles_$tmp_save_1+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$ac_includes
-int
-main ()
-{
-FILE *stream; va_list ap; std::vfprintf(stream, "", ap);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- eval "ac_cv_compiles_$tmp_save_1=yes"
-else
- eval "ac_cv_compiles_$tmp_save_1=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-if eval "test \"`echo '$''{'ac_cv_compiles_$tmp_save_1'}'`\" = yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define HAVE_PROTOTYPE_STD__VFPRINTF 1" >>confdefs.h
-
- :
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::vsnprintf (in cstdarg cstdio)" >&5
$as_echo_n "checking for std::vsnprintf (in cstdarg cstdio)... " >&6; }
#endif
/* on some platforms, tcpd.h needs stdio.h */
#include <stdio.h>
- #ifdef HAVE_SYS_TYPES_H
/* on some platforms, tcpd.h needs sys/types.h */
#include <sys/types.h>
- #endif
#include <tcpd.h>
#ifdef __cplusplus
}
if test "${with_libsndfile+set}" = set; then :
withval=$with_libsndfile; case "$withval" in
yes)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- $as_echo "#define WITH_SNDFILE 1" >>confdefs.h
-
- SNDFILELIBS="-lsndfile"
- ;;
- *)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- ;;
- esac
-else
- SAVELIBS="$LIBS"
- LIBS="$LIBS -lsndfile"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ SAVELIBS="$LIBS"
+ LIBS="$LIBS -lsndfile"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sndfile.h>
int
if ac_fn_cxx_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
- $as_echo "#define WITH_SNDFILE 1" >>confdefs.h
+ $as_echo "#define WITH_SNDFILE 1" >>confdefs.h
- SNDFILELIBS="-lsndfile"
+ SNDFILELIBS="-lsndfile"
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
- LIBS="$SAVELIBS"
+ LIBS="$SAVELIBS"
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ;;
+ esac
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
+
# Check whether --with-libiconvinc was given.
if test "${with_libiconvinc+set}" = set; then :
withval=$with_libiconvinc; case $withval in #(
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether iterator category contiguous is declared" >&5
-$as_echo_n "checking whether iterator category contiguous is declared... " >&6; }
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-
- #include <iterator>
- int main(){typedef std::contiguous_iterator_tag category;return 0;}
-
-
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- dcmtk_have_iter_cat=yes
-else
- dcmtk_have_iter_cat=no
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- if test "$dcmtk_have_iter_cat" = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-$as_echo "#define HAVE_CONTIGUOUS_ITERATOR_CATEGORY 1" >>confdefs.h
-
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
-
-
-
-
CFLAGS="$DEBUGCFLAGS $CFLAGS"
CXXFLAGS="$DEBUGCXXFLAGS $CXXFLAGS"
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by dcmtk $as_me 3.6.9, which was
+This file was extended by dcmtk $as_me 3.7.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-dcmtk config.status 3.6.9
+dcmtk config.status 3.7.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(dcmtk, 3.6.9, [bugs@dcmtk.org], [dcmtk-3.6.9], [https://www.dcmtk.org/])
+AC_INIT(dcmtk, 3.7.0, [bugs@dcmtk.org], [dcmtk-3.7.0], [https://www.dcmtk.org/])
AC_PREREQ(2.60)
AC_CONFIG_SRCDIR(Makefile.in)
AC_CONFIG_HEADERS(include/dcmtk/config/osconfig.h)
dnl Additional Package Information
dnl -------------------------------------------------------
-PACKAGE_VERSION_NUMBER=368
-PACKAGE_VERSION_SUFFIX="+"
-PACKAGE_DATE="DEV"
+PACKAGE_VERSION_NUMBER=370
+PACKAGE_VERSION_SUFFIX=""
+PACKAGE_DATE="2025-12-15"
AC_DEFINE_UNQUOTED(PACKAGE_VERSION_NUMBER,${PACKAGE_VERSION_NUMBER},[Define to the version number of this package.])
AC_DEFINE_UNQUOTED(PACKAGE_VERSION_SUFFIX,"${PACKAGE_VERSION_SUFFIX}",[Define to the version suffix of this package.])
AC_DEFINE_UNQUOTED(PACKAGE_DATE,"${PACKAGE_DATE}",[Define to the release date of this package.])
AC_CHECK_TYPES(char16_t)
-AC_CHECK_TYPES([sigjmp_buf], [], [], [[#include <setjmp.h>]])
-
dnl -------------------------------------------------------
dnl Check for libc library functions
dnl -------------------------------------------------------
AC_FUNC_MEMCMP
AC_TYPE_SIGNAL
AC_CHECK_FUNCS(gethostid sysinfo)
-AC_CHECK_FUNCS(itoa atoll)
-AC_CHECK_FUNCS(bcmp)
-AC_CHECK_FUNCS(getpid mktemp mkstemp)
-AC_CHECK_FUNCS(stat)
+AC_CHECK_FUNCS(atoll)
+AC_CHECK_FUNCS(mkstemp)
AC_CHECK_FUNCS(malloc_debug)
-AC_CHECK_FUNCS(strdup index rindex access)
AC_CHECK_FUNCS(uname cuserid getlogin getlogin_r)
AC_CHECK_FUNCS(usleep)
AC_CHECK_FUNCS(flock lockf)
-AC_CHECK_FUNCS(listen)
AC_CHECK_FUNCS(gethostbyname_r)
AC_CHECK_FUNCS(gethostbyaddr_r getgrnam_r getpwnam_r)
-AC_CHECK_FUNCS(getrusage)
AC_CHECK_FUNCS(gettimeofday)
AC_CHECK_FUNCS(waitpid)
AC_CHECK_FUNCS(getuid geteuid setuid getpwnam getgrnam)
AC_CHECK_FUNCS(sleep fork)
AC_CHECK_FUNCS(_findfirst)
AC_CHECK_FUNCS(strlcpy strlcat)
-AC_CHECK_FUNCS(vsnprintf)
AC_CHECK_FUNCS(popen pclose)
AC_CHECK_FUNCS(readdir_r)
AC_FUNC_FSEEKO
dnl Check for header files and functions needed by oflog
dnl -------------------------------------------------------
-AC_DEFUN([TYPE_SOCKLEN_T],
-[
-AH_TEMPLATE(socklen_t, [Define to int if undefined.])
-AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t,
-[
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/types.h>
- #include <sys/socket.h>]], [[socklen_t len = 42; return 0;]])],[ac_cv_type_socklen_t=yes],[ac_cv_type_socklen_t=no])
-])
- if test $ac_cv_type_socklen_t != yes; then
- AC_DEFINE(socklen_t, int)
- fi
-])
-
AC_CHECK_FUNCS(ftime gmtime_r localtime_r lstat nanosleep fcntl)
AC_CHECK_FUNCS(htons htonl ntohs ntohl)
AC_CHECK_HEADERS(netinet/in.h)
AC_CHECK_HEADERS(syslog.h)
-TYPE_SOCKLEN_T
AH_TEMPLATE(HAVE_ENAMETOOLONG, [Define if your system provides ENAMETOOLONG errno value.])
AC_COMPILE_IFELSE(
AC_CHECK_PROTOTYPE(strcasestr, string.h)
-dnl -------------------------------------------------------
-dnl Check for libm library functions
-dnl -------------------------------------------------------
-
-SAVELIBS="$LIBS"
-LIBS="$LIBS -lm"
-AC_CHECK_FUNCS(finite)
-LIBS="$SAVELIBS"
-
dnl -------------------------------------------------------
dnl Perform remaining tests with C++ compiler
dnl -------------------------------------------------------
AC_LANG(C++)
-AC_CXX_STD_NOTHROW
-AC_CXX_NOTHROW_DELETE
-AC_CXX_STATIC_ASSERT
-
dnl -------------------------------------------------------
dnl Check for Debug Mode
dnl -------------------------------------------------------
AC_CHECK_GXXLIB
-dnl Some C++ compilers have problems with recursive main calls
-dnl (e.g. Sun C++ 4.2). In this case we must test another function
-dnl to link.
-AC_CHECK_LIB(nsl, main)
-if test $ac_cv_lib_nsl_main = no ; then
-AC_CHECK_LIB(nsl, gethostbyname)
-fi
-AC_CHECK_LIB(socket, main)
-if test $ac_cv_lib_socket_main = no ; then
-AC_CHECK_LIB(socket, socket)
-fi
-
dnl Some newer versions of OpenSSL must be linked against libdl.
dnl We just check whether libdl exists and in this case always
dnl add -ldl to OPENSSLLIBS. The same applies for OPENJPEG.
AC_CHECK_HEADERS(alloca.h)
AC_CHECK_HEADERS(atomic)
AC_CHECK_HEADERS(arpa/inet.h)
-AC_CHECK_HEADERS(fcntl.h)
AC_CHECK_HEADERS(fnmatch.h)
AC_CHECK_HEADERS(grp.h)
AC_CHECK_HEADERS(ieeefp.h)
AC_CHECK_HEADERS(io.h)
AC_CHECK_HEADERS(iostream)
AC_CHECK_HEADERS(libc.h)
-AC_CHECK_HEADERS(malloc.h)
AC_CHECK_HEADERS(mqueue.h)
AC_CHECK_HEADERS(new)
AC_CHECK_HEADERS(netdb.h)
AC_CHECK_HEADERS(pwd.h)
AC_CHECK_HEADERS(semaphore.h)
AC_CHECK_HEADERS(cstddef)
-AC_CHECK_HEADERS(stdint.h)
AC_CHECK_HEADERS(strings.h)
AC_CHECK_HEADERS(synch.h)
-AC_CHECK_HEADERS(sys/errno.h)
AC_CHECK_HEADERS(sys/file.h)
AC_CHECK_HEADERS(sys/msg.h)
AC_CHECK_HEADERS(sys/param.h)
AC_CHECK_HEADERS(sys/resource.h)
AC_CHECK_HEADERS(sys/select.h)
AC_CHECK_HEADERS(sys/socket.h)
-AC_CHECK_HEADERS(sys/stat.h)
AC_CHECK_HEADERS(sys/syscall.h)
AC_CHECK_HEADERS(sys/systeminfo.h)
AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_HEADERS(sys/timeb.h)
-AC_CHECK_HEADERS(sys/types.h)
AC_CHECK_HEADERS(sys/un.h)
AC_CHECK_HEADERS(sys/utime.h)
AC_CHECK_HEADERS(sys/utsname.h)
AC_TYPEDEF(ssize_t, long)
AC_TYPEDEF(pid_t, int)
AC_C_CHAR_UNSIGNED
-AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)
AC_CHECK_SIZEOF(long)
-AC_CHECK_SIZEOF(float)
-AC_CHECK_SIZEOF(double)
AC_CHECK_SIZEOF(void *)
AC_STRUCT_TM
AC_MY_SYMBOL_EXISTS([__FUNCTION__])
dnl the acconfig.h file. This is because the macros are specific to the
dnl DCMTK project and are not supported by GNU autoheader.
-AC_CHECK_PROTOTYPE(feenableexcept, fenv.h)
AC_CHECK_PROTOTYPE(_stricmp, string.h)
-AC_CHECK_INTP_ACCEPT(sys/types.h sys/socket.h)
-AC_CHECK_PROTOTYPE(finite, math.h)
-AC_CHECK_PROTOTYPE(std::isinf, cmath)
-AC_CHECK_PROTOTYPE(std::isnan, cmath)
AC_CHECK_PROTOTYPE(flock, sys/file.h)
AC_CHECK_PROTOTYPE(gethostbyname_r, libc.h unistd.h stdlib.h netdb.h)
AC_CHECK_PROTOTYPE(gethostbyaddr_r, libc.h unistd.h stdlib.h netdb.h)
if test $ac_cv_prototype_strerror_r = yes ; then
AC_CHECK_CHARP_STRERROR_R(string.h)
fi
-AC_CHECK_INTP_GETSOCKOPT(sys/types.h sys/socket.h)
AC_CHECK_PROTOTYPE(gettimeofday, sys/time.h unistd.h)
-AC_CHECK_PROTOTYPE(mktemp, libc.h unistd.h stdlib.h)
-AC_CHECK_PROTOTYPE(mkstemp, libc.h unistd.h stdlib.h)
AC_CHECK_PROTOTYPE(strcasecmp, string.h)
AC_CHECK_PROTOTYPE(strncasecmp, string.h)
AC_CHECK_PROTOTYPE(usleep, libc.h unistd.h stdlib.h)
AC_CHECK_PROTOTYPE(vsnprintf, stdio.h stdarg.h)
AC_CHECK_PROTOTYPE(waitpid, sys/wait.h sys/time.h sys/resource.h)
+
dnl -------------------------------------------------------
dnl Check for the usage of standard C++ headers
dnl -------------------------------------------------------
-AC_CHECK_STD_NAMESPACE
-AC_CHECK_COMPILES(std::vfprintf, cstdarg cstdio,
- [FILE *stream; va_list ap; std::vfprintf(stream, "", ap);])
AC_CHECK_COMPILES(std::vsnprintf, cstdarg cstdio,
[char buf[256]; va_list ap; std::vsnprintf(buf, 0, "", ap);])
#endif
/* on some platforms, tcpd.h needs stdio.h */
#include <stdio.h>
- #ifdef HAVE_SYS_TYPES_H
/* on some platforms, tcpd.h needs sys/types.h */
#include <sys/types.h>
- #endif
#include <tcpd.h>
#ifdef __cplusplus
}
AC_MSG_CHECKING(whether to include libsndfile support)
AH_TEMPLATE(WITH_SNDFILE, [Define if we are compiling with libsndfile support.])
AC_ARG_WITH(libsndfile,
- [AS_HELP_STRING([--with-libsndfile], [include libsndfile support (default: auto)])
+ [AS_HELP_STRING([--with-libsndfile], [include libsndfile support (default: no)])
AS_HELP_STRING([--without-libsndfile], [don't include libsndfile support])],
[ case "$withval" in
yes)
- AC_MSG_RESULT(yes)
- AC_DEFINE(WITH_SNDFILE)
- SNDFILELIBS="-lsndfile"
+ SAVELIBS="$LIBS"
+ LIBS="$LIBS -lsndfile"
+ AC_TRY_LINK([#include <sndfile.h>], [char buffer [128]; sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer));],
+ [ AC_MSG_RESULT(yes)
+ AC_DEFINE(WITH_SNDFILE)
+ SNDFILELIBS="-lsndfile" ],
+ [ AC_MSG_RESULT(no) ])
+ LIBS="$SAVELIBS"
;;
*)
AC_MSG_RESULT(no)
;;
esac ],
- [ SAVELIBS="$LIBS"
- LIBS="$LIBS -lsndfile"
- AC_TRY_LINK([#include <sndfile.h>], [char buffer [128]; sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer));],
- [ AC_MSG_RESULT(yes)
- AC_DEFINE(WITH_SNDFILE)
- SNDFILELIBS="-lsndfile" ],
- [AC_MSG_RESULT(no)])
- LIBS="$SAVELIBS"]
+ [ AC_MSG_RESULT(no) ]
)
+
dnl -------------------------------------------------------
dnl Check for libiconv support
dnl -------------------------------------------------------
[AC_MSG_RESULT(no)])
-dnl -------------------------------------------------------
-dnl Test for defined iterator categories
-dnl -------------------------------------------------------
-
-AC_CHECK_ITERATOR_CATEGORY([contiguous],[HAVE_CONTIGUOUS_ITERATOR_CATEGORY])
-
-
dnl -------------------------------------------------------
dnl Set optimizer and debug compiler flags
dnl -------------------------------------------------------
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
-datadir='${datarootdir}/dcmtk-3.6.9'
-sysconfdir='${prefix}/etc/dcmtk-3.6.9'
+datadir='${datarootdir}/dcmtk-3.7.0'
+sysconfdir='${prefix}/etc/dcmtk-3.7.0'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
includedir='${prefix}/include'
oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/dcmtk-3.6.9'
+docdir='${datarootdir}/doc/dcmtk-3.7.0'
infodir='${datarootdir}/info'
htmldir='${docdir}/html'
dvidir='${docdir}'
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
- --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk-3.6.9]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc/dcmtk-3.7.0]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
- --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk-3.6.9]
+ --datadir=DIR read-only arch.-independent data [DATAROOTDIR/dcmtk-3.7.0]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
- --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk-3.6.9]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/dcmtk-3.7.0]
--htmldir=DIR html documentation [DOCDIR/html]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
test (see DCMTK issue #1018). The test has, therefore, been disabled. This
macro re-enables the old behavior.
-DCMTK_ENABLE_UNSAFE_VSNPRINTF
- Affected: ofstd
- Type of modification: Activates feature
- Explanation: DCMTK requires the snprintf(3)/vsnprintf(3) function, which was
- introduced with C99 and may not be supported by very old compilers. As a
- "last resort", an implementation internally using sprintf/vsprintf can be
- enabled with this macro, which allows the user to compile DCMTK on platforms
- that do not have the new functions.
- The implementation allocates a buffer that is 1 kByte larger than the "size"
- parameter, formats the string into that buffer, and then uses strlcpy() to
- copy the formatted string into the output buffer, truncating if necessary.
- This will work in most cases, since few snprintf calls should overrun their
- buffer by more than 1K, but it can be easily abused by a malicious attacker
- to cause a buffer overrun.
- Therefore, this implementation should only be used as a "last resort" and we
- strongly advise against using it in production code.
-
DCMTK_GUI
Affected: all modules
Type of modification: Activates experimental or rarely used feature
#define ENVIRONMENT_PATH_SEPARATOR ':'
#endif
-/* Define to 1 if you have the `access' function. */
-#undef HAVE_ACCESS
-
/* Define to 1 if you have the <alloca.h> header file. */
#undef HAVE_ALLOCA_H
/* Define if the compiler supports __attribute__((deprecated("message"))). */
#undef HAVE_ATTRIBUTE_DEPRECATED_MSG
-/* Define to 1 if you have the `bcmp' function. */
-#undef HAVE_BCMP
-
/* Define to 1 if the system has the type `char16_t'. */
#undef HAVE_CHAR16_T
instead of int. */
#undef HAVE_CHARP_STRERROR_R
-/* Define if the contiguous iterator category is supported. */
-#undef HAVE_CONTIGUOUS_ITERATOR_CATEGORY
-
/* Define to 1 if you have the <cstddef> header file. */
#undef HAVE_CSTDDEF
/* Define to 1 if you have the `fcntl' function. */
#undef HAVE_FCNTL
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
/* Define to 1 if you have the `fgetln' function. */
#undef HAVE_FGETLN
-/* Define to 1 if you have the `finite' function. */
-#undef HAVE_FINITE
-
/* Define to 1 if you have the `flock' function. */
#undef HAVE_FLOCK
/* Define to 1 if you have the `getlogin_r' function. */
#undef HAVE_GETLOGIN_R
-/* Define to 1 if you have the `getpid' function. */
-#undef HAVE_GETPID
-
/* Define to 1 if you have the `getpwnam' function. */
#undef HAVE_GETPWNAM
/* Define to 1 if you have the `getpwnam_r' function. */
#undef HAVE_GETPWNAM_R
-/* Define to 1 if you have the `getrusage' function. */
-#undef HAVE_GETRUSAGE
-
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define to 1 if you have the <ieeefp.h> header file. */
#undef HAVE_IEEEFP_H
-/* Define to 1 if you have the `index' function. */
-#undef HAVE_INDEX
-
/* Define to 1 if the system has the type `int64_t'. */
#undef HAVE_INT64_T
-/* Define if your system declares argument 3 of accept() as int * instead of
- size_t * or socklen_t *. */
-#undef HAVE_INTP_ACCEPT
-
-/* Define if your system declares argument 5 of getsockopt() as int * instead
- of size_t * or socklen_t. */
-#undef HAVE_INTP_GETSOCKOPT
-
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <io.h> header file. */
#undef HAVE_IO_H
-/* Define to 1 if you have the `itoa' function. */
-#undef HAVE_ITOA
-
/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H
/* Define to 1 if you have the <libc.h> header file. */
#undef HAVE_LIBC_H
-/* Define to 1 if you have the `nsl' library (-lnsl). */
-#undef HAVE_LIBNSL
-
/* Define to 1 if you have the <libpng/png.h> header file. */
#undef HAVE_LIBPNG_PNG_H
-/* Define to 1 if you have the `socket' library (-lsocket). */
-#undef HAVE_LIBSOCKET
-
-/* Define to 1 if you have the `listen' function. */
-#undef HAVE_LISTEN
-
/* Define to 1 if you have the `localtime_r' function. */
#undef HAVE_LOCALTIME_R
/* Define to 1 if you have the `malloc_debug' function. */
#undef HAVE_MALLOC_DEBUG
-/* Define to 1 if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mkstemp' function. */
#undef HAVE_MKSTEMP
-/* Define to 1 if you have the `mktemp' function. */
-#undef HAVE_MKTEMP
-
/* Define to 1 if you have the <mqueue.h> header file. */
#undef HAVE_MQUEUE_H
/* Define to 1 if you have the <new> header file. */
#undef HAVE_NEW
-/* Define if the compiler supports operator delete (std::nothrow). */
-#undef HAVE_NOTHROW_DELETE
-
/* Define `pid_t' to `int' if <sys/types.h> does not define. */
#undef HAVE_NO_TYPEDEF_PID_T
/* Define to 1 if you have the `popen' function. */
#undef HAVE_POPEN
-/* Define if your system has a prototype for feenableexcept in fenv.h. */
-#undef HAVE_PROTOTYPE_FEENABLEEXCEPT
-
-/* Define if your system has a prototype for finite in math.h. */
-#undef HAVE_PROTOTYPE_FINITE
-
/* Define if your system has a prototype for flock in sys/file.h. */
#undef HAVE_PROTOTYPE_FLOCK
unistd.h. */
#undef HAVE_PROTOTYPE_GETTIMEOFDAY
-/* Define if your system has a prototype for mkstemp in libc.h unistd.h
- stdlib.h. */
-#undef HAVE_PROTOTYPE_MKSTEMP
-
-/* Define if your system has a prototype for mktemp in libc.h unistd.h
- stdlib.h. */
-#undef HAVE_PROTOTYPE_MKTEMP
-
-/* Define if your system has a prototype for std::isinf in cmath. */
-#undef HAVE_PROTOTYPE_STD__ISINF
-
-/* Define if your system has a prototype for std::isnan in cmath. */
-#undef HAVE_PROTOTYPE_STD__ISNAN
-
-/* Define if your system has a prototype for std::vfprintf in cstdarg cstdio.
- */
-#undef HAVE_PROTOTYPE_STD__VFPRINTF
-
/* Define if your system has a prototype for std::vsnprintf in cstdarg cstdio.
*/
#undef HAVE_PROTOTYPE_STD__VSNPRINTF
/* Define to 1 if you have the `readdir_r' function. */
#undef HAVE_READDIR_R
-/* Define to 1 if you have the `rindex' function. */
-#undef HAVE_RINDEX
-
/* Define to 1 if you have the <semaphore.h> header file. */
#undef HAVE_SEMAPHORE_H
/* Define to 1 if you have the `setuid' function. */
#undef HAVE_SETUID
-/* Define to 1 if the system has the type `sigjmp_buf'. */
-#undef HAVE_SIGJMP_BUF
-
/* Define to 1 if you have the `sleep' function. */
#undef HAVE_SLEEP
-/* Define to 1 if you have the `stat' function. */
-#undef HAVE_STAT
-
-/* Define if the compiler supports static_assert. */
-#undef HAVE_STATIC_ASSERT
-
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
-/* Define if ANSI standard C++ includes use std namespace. */
-#undef HAVE_STD_NAMESPACE
-
-/* Define if the compiler supports std::nothrow. */
-#undef HAVE_STD__NOTHROW
-
/* Define if STL's algorithm should be used. */
#undef HAVE_STL_ALGORITHM
/* Define if STL's vector should be used. */
#undef HAVE_STL_VECTOR
-/* Define to 1 if you have the `strdup' function. */
-#undef HAVE_STRDUP
-
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
*/
#undef HAVE_SYS_DIR_H
-/* Define to 1 if you have the <sys/errno.h> header file. */
-#undef HAVE_SYS_ERRNO_H
-
/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define if variable-length arrays are supported in C. */
#undef HAVE_VLA
-/* Define to 1 if you have the `vsnprintf' function. */
-#undef HAVE_VSNPRINTF
-
/* Define to 1 if you have the `waitpid' function. */
#undef HAVE_WAITPID
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
-/* The size of `double', as computed by sizeof. */
-#undef SIZEOF_DOUBLE
-
-/* The size of `float', as computed by sizeof. */
-#undef SIZEOF_FLOAT
-
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
-/* The size of `short', as computed by sizeof. */
-#undef SIZEOF_SHORT
-
/* The size of `void *', as computed by sizeof. */
#undef SIZEOF_VOID_P
# undef __CHAR_UNSIGNED__
#endif
-/* Define to int if undefined. */
-#undef socklen_t
-
#if defined(HAVE_CXX11) && defined(__cplusplus) && __cplusplus < 201103L
#error \
DCMTK was configured to use C++11 features, but your compiler does not or was not configured to provide them.
/*
*
- * Copyright (C) 2015-2024, OFFIS e.V.
+ * Copyright (C) 2015-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
static inline OFBool isnan( float f )
{
-#ifdef HAVE_PROTOTYPE_STD__ISNAN
return STD_NAMESPACE isnan(f);
-#else
- return ::isnan(f);
-#endif
}
static inline OFBool isnan( double d )
{
-#ifdef HAVE_PROTOTYPE_STD__ISNAN
return STD_NAMESPACE isnan(d);
-#else
- return ::isnan(d);
-#endif
}
static inline OFBool isinf( float f )
{
-#ifdef HAVE_PROTOTYPE_STD__ISINF
return STD_NAMESPACE isinf( f );
-#else
- return ::isinf( f );
-#endif
}
static inline OFBool isinf( double d )
{
-#ifdef HAVE_PROTOTYPE_STD__ISINF
return STD_NAMESPACE isinf( d );
-#else
- return ::isinf( d );
-#endif
+ }
+
+ static inline double sqrt( double d )
+ {
+ return STD_NAMESPACE sqrt(d);
}
};
-oficonv ofstd oflog dcmdata dcmiod dcmfg dcmseg dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmpstat dcmrt dcmtract dcmpmap dcmect dcmapps
+oficonv ofstd oflog dcmdata dcmimgle dcmimage dcmjpeg dcmjpls dcmtls dcmnet dcmsr dcmsign dcmwlm dcmqrdb dcmrt dcmiod dcmpstat dcmfg dcmseg dcmtract dcmpmap dcmect dcmapps
\ No newline at end of file
endforeach()
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(dcm2img dcmjpeg dcmjpls dcmimage dcmimgle dcmdata oflog oficonv ofstd)
+DCMTK_TARGET_LINK_MODULES(dcm2img dcmjpeg dcmjpls)
+cn --conv-never
never convert color space
+bits stored:
+
+ +bs --bits-stored-fix
+ correct inconsistent bits stored value (default)
+
+ # If the value of BitsStored in the compressed bitstream is smaller
+ # than the value in the DICOM dataset, update the value in the dataset
+ # (JPEG compressed images only)
+
+ -bs --bits-stored-keep
+ preserve inconsistent bits stored value
+
+ # Keep the value of BitsStored even if inconsistent with the
+ # compressed bitstream. This may help in correctly decoding some
+ # defective images JPEG compressed images only)
+
workaround options for incorrect encodings (JPEG compressed images only):
+w6 --workaround-pred6
\section dcm2img_copyright COPYRIGHT
-Copyright (C) 2001-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2001-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 1996-2024, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#endif
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_BINARY */
-#endif
#ifdef HAVE_IO_H
#include <io.h> /* for setmode() on Windows */
#endif
// no filename extension, return BMP as the default for files
if (pos == OFString_npos)
{
- OFLOG_WARN(dcm2imgLogger, "no filename extension specified, writing BMP file.");
+ OFLOG_WARN(dcm2imgLogger, "no filename extension specified, writing BMP file");
return EFT_BMP;
}
#endif /* WITH_OPENJPEG */
#endif /* BUILD_DCM2IMG_AS_DCM2KIMG */
- OFLOG_WARN(dcm2imgLogger, "unsupported filename extension '" << extension << "', writing BMP file.");
+ OFLOG_WARN(dcm2imgLogger, "unsupported filename extension '" << extension << "', writing BMP file");
return EFT_BMP;
}
OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, consoleDescription, rcsid);
OFCommandLine cmd;
+ int exitCode = 0;
+
E_FileReadMode opt_readMode = ERM_autoDetect; /* default: fileformat or dataset */
E_TransferSyntax opt_transferSyntax = EXS_Unknown; /* default: xfer syntax recognition */
OFBool opt_predictor6WorkaroundEnable = OFFalse;
OFBool opt_cornellWorkaroundEnable = OFFalse;
OFBool opt_forceSingleFragmentPerFrame = OFFalse;
+ OFBool opt_preserveBitsStored = OFFalse;
// JPEG-LS parameters
OFBool opt_true_lossless = OFFalse;
int opt_imageInfo = 0; /* default: no info */
int opt_suppressOutput = 0; /* default: create output */
- E_FileType opt_fileType = EFT_default;
- /* (binary for file output and ASCII for stdout) */
+ E_FileType opt_fileType = EFT_default; /* default: auto */
OFCmdUnsignedInt opt_fileBits = 0; /* default: 0 */
const char * opt_ifname = NULL;
const char * opt_ofname = NULL;
cmd.addOption("--conv-always", "+ca", "always convert YCbCr to RGB");
cmd.addOption("--conv-never", "+cn", "never convert color space");
+ cmd.addSubGroup("bits stored:");
+ cmd.addOption("--bits-stored-fix", "+bs", "correct inconsistent bits stored value (default)");
+ cmd.addOption("--bits-stored-keep", "-bs", "preserve inconsistent bits stored value");
+
cmd.addSubGroup("workaround options for incorrect encodings (JPEG compressed images only):");
cmd.addOption("--workaround-pred6", "+w6", "enable workaround for JPEG lossless images\nwith overflow in predictor 6");
cmd.addOption("--workaround-incpl", "+wi", "enable workaround for incomplete JPEG data");
if (cmd.findOption("--check-lut-depth"))
opt_compatibilityMode |= CIF_CheckLutBitDepth;
if (cmd.findOption("--ignore-mlut-depth"))
+ {
+ app.checkConflict("--ignore-mlut-depth", "--check-lut-depth", (opt_compatibilityMode & CIF_CheckLutBitDepth) > 0);
opt_compatibilityMode |= CIF_IgnoreModalityLutBitDepth;
+ }
if (cmd.findOption("--ignore-vlut-depth"))
+ {
+ app.checkConflict("--ignore-vlut-depth", "--check-lut-depth", (opt_compatibilityMode & CIF_CheckLutBitDepth) > 0);
opt_ignoreVoiLutDepth = OFTrue;
+ }
/* image processing options: frame selection */
opt_decompCSconversion = EDC_never;
cmd.endOptionBlock();
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--bits-stored-fix")) opt_preserveBitsStored = OFFalse;
+ if (cmd.findOption("--bits-stored-keep")) opt_preserveBitsStored = OFTrue;
+ cmd.beginOptionBlock();
+
if (cmd.findOption("--workaround-pred6")) opt_predictor6WorkaroundEnable = OFTrue;
if (cmd.findOption("--workaround-incpl")) opt_forceSingleFragmentPerFrame = OFTrue;
if (cmd.findOption("--workaround-cornell")) opt_cornellWorkaroundEnable = OFTrue;
opt_fileType = EFT_JPLS;
#ifdef BUILD_DCM2IMG_AS_DCM2KIMG
if (cmd.findOption("--write-jp2k-cs"))
- {
opt_fileType = EFT_JP2K_CS;
- }
#ifdef WITH_OPENJPEG
if (cmd.findOption("--write-jp2k"))
{
if (cmd.findOption("--write-pastel-pnm"))
opt_fileType = EFT_PastelPNM;
#endif
- if (opt_ofname && (opt_fileType == EFT_default|| cmd.findOption("--write-auto")))
- opt_fileType = getFileTypeByExtension(opt_ofname);
+ if (cmd.findOption("--write-auto"))
+ opt_fileType = EFT_default;
cmd.endOptionBlock();
}
<< DCM_DICT_ENVIRONMENT_VARIABLE);
}
- if (opt_suppressOutput && opt_ofname)
- OFLOG_WARN(dcm2imgLogger, "ignoring parameter bitmap-out because of option --no-output");
+ if (opt_ofname)
+ {
+ if (opt_suppressOutput)
+ OFLOG_WARN(dcm2imgLogger, "ignoring parameter bitmap-out because of option --no-output");
+ else if (opt_fileType == EFT_default)
+ opt_fileType = getFileTypeByExtension(opt_ofname);
+ }
OFLOG_INFO(dcm2imgLogger, "reading DICOM file: " << opt_ifname);
// register JPEG decompression codecs
DJDecoderRegistration::registerCodecs(opt_decompCSconversion, EUC_default,
EPC_default, opt_predictor6WorkaroundEnable, opt_cornellWorkaroundEnable,
- opt_forceSingleFragmentPerFrame);
+ opt_forceSingleFragmentPerFrame, opt_preserveBitsStored);
// register JPEG-LS decompression codecs
DJLSDecoderRegistration::registerCodecs();
if (opt_use_openjpeg)
{
// register global OpenJPEG decompression codecs
- O2DecoderRegistration::registerCodecs(EJ2UC_default, EJ2PC_restore, OFstatic_cast(int, openJPEGNumThreads), 0 /* decoder flags */, OFTrue, OFTrue);
+ O2DecoderRegistration::registerCodecs(EJ2UC_default, EJ2PC_restore, OFstatic_cast(int, openJPEGNumThreads), 0 /* decoder flags */, OFTrue, OFTrue, opt_preserveBitsStored);
}
else
{
// register global JasPer decompression codecs
- D2DecoderRegistration::registerCodecs();
+ D2DecoderRegistration::registerCodecs(EJ2UC_default, EJ2PC_restore, OFTrue, OFTrue, opt_preserveBitsStored);
}
#else /* WITH_OPENJPEG */
// register global JasPer decompression codecs
- D2DecoderRegistration::registerCodecs();
+ D2DecoderRegistration::registerCodecs(EJ2UC_default, EJ2PC_restore, OFTrue, OFTrue, opt_preserveBitsStored);
#endif /* WITH_OPENJPEG */
#endif /* BUILD_DCM2IMG_AS_DCM2KIMG */
+ DcmDataset *dataset = NULL;
+ DicomImage *di = NULL;
+ DiDisplayFunction *disp = NULL;
+ E_TransferSyntax xfer = EXS_Unknown;
+
DcmFileFormat *dfile = new DcmFileFormat();
OFCondition cond = dfile->loadFile(opt_ifname, opt_transferSyntax, EGL_withoutGL, DCM_MaxReadLength, opt_readMode);
if (cond.bad())
{
OFLOG_FATAL(dcm2imgLogger, cond.text() << ": reading file: " << opt_ifname);
- return 1;
+ delete dfile;
+ exitCode = 1;
+ goto cleanup;
}
OFLOG_INFO(dcm2imgLogger, "preparing pixel data");
- DcmDataset *dataset = dfile->getDataset();
- E_TransferSyntax xfer = dataset->getOriginalXfer();
+ dataset = dfile->getDataset();
+ xfer = dataset->getOriginalXfer();
Sint32 frameCount;
if (dataset->findAndGetSint32(DCM_NumberOfFrames, frameCount).bad())
opt_compatibilityMode |= CIF_UsePartialAccessToPixelData;
}
- DicomImage *di = new DicomImage(dfile, xfer, opt_compatibilityMode, opt_frame - 1, opt_frameCount);
+ di = new DicomImage(dfile, xfer, opt_compatibilityMode, opt_frame - 1, opt_frameCount);
if (di == NULL)
{
OFLOG_FATAL(dcm2imgLogger, "Out of memory");
- return 1;
+ exitCode = 1;
+ goto cleanup;
}
if (di->getStatus() != EIS_Normal)
{
OFLOG_FATAL(dcm2imgLogger, DicomImage::getString(di->getStatus()));
- return 1;
+ exitCode = 1;
+ goto cleanup;
}
/* create & set display function */
- DiDisplayFunction *disp = NULL;
if (!opt_displayFile.empty())
{
if (opt_displayFunction == 1)
if (opt_frame != di->getFirstFrame() + 1)
{
OFLOG_FATAL(dcm2imgLogger, "cannot select frame " << opt_frame << ", invalid frame number");
- return 1;
+ exitCode = 1;
+ goto cleanup;
}
/* convert to grayscale if image is not monochrome */
if ((opt_convertToGrayscale) && (!di->isMonochrome()))
{
di = convertToGrayscale(di);
- if (di == NULL) return 1;
+ if (di == NULL)
+ {
+ exitCode = 1;
+ goto cleanup;
+ }
}
/* process overlay parameters */
int result = processVOIParameters(di, opt_windowType, opt_windowParameter,
opt_windowCenter, opt_windowWidth, opt_voiFunction, opt_ignoreVoiLutDepth,
opt_roiLeft, opt_roiTop, opt_roiWidth, opt_roiHeight);
- if (result) return result;
+ if (result)
+ {
+ exitCode = result;
+ goto cleanup;
+ }
/* process presentation LUT parameters */
processPLUTParameters(di, opt_presShape);
/* perform clipping */
di = performClipping(di, opt_useClip, opt_scaleType, opt_left,
opt_top, opt_width, opt_height);
- if (di == NULL) return 1;
+ if (di == NULL)
+ {
+ exitCode = 1;
+ goto cleanup;
+ }
/* perform rotation */
performRotation(di, opt_rotateDegree);
di = performScaling(di, opt_useClip, opt_scaleType, opt_left, opt_top,
opt_width, opt_height, opt_scale_factor, opt_scale_size,
opt_useInterpolation, opt_useAspectRatio);
- if (di == NULL) return 1;
+ if (di == NULL)
+ {
+ exitCode = 1;
+ goto cleanup;
+ }
/* write selected frame(s) to file */
if (ofile == NULL)
{
OFLOG_FATAL(dcm2imgLogger, "cannot create file " << ofname);
- return 1;
+ exitCode = 1;
+ goto cleanup;
}
} else {
/* output to stdout */
{
if (fclose(ofile))
{
- OFLOG_FATAL(dcm2imgLogger, "Error while closing file, content may be incomplete.");
- return 1;
+ OFLOG_FATAL(dcm2imgLogger, "error while closing file, content may be incomplete");
+ exitCode = 1;
+ goto cleanup;
}
}
if (!result)
{
OFLOG_FATAL(dcm2imgLogger, "cannot write frame");
- return 1;
+ exitCode = 1;
+ goto cleanup;
}
}
}
/* done, now cleanup. */
OFLOG_INFO(dcm2imgLogger, "cleaning up memory");
+
+ cleanup:
+
delete di;
delete disp;
#endif /* WITH_OPENJPEG */
#endif /* BUILD_DCM2IMG_AS_DCM2KIMG */
- return 0;
+ return exitCode;
}
include_directories(${LIBXML_INCDIR})
# declare executables
-foreach(PROGRAM dcm2xml dcmconv dcmcrle dcmdrle dcmdump dcmftest dcmgpdir dump2dcm xml2dcm stl2dcm pdf2dcm dcm2pdf img2dcm dcm2json cda2dcm dcm2cda)
+foreach(PROGRAM dcm2xml dcmconv dcmcrle dcmdrle dcmdump dcmftest dcmgpdir dump2dcm xml2dcm stl2dcm pdf2dcm dcm2pdf img2dcm dcm2json cda2dcm dcm2cda json2dcm dcmencap dcmdecap)
DCMTK_ADD_EXECUTABLE(${PROGRAM} ${PROGRAM}.cc)
endforeach()
+
DCMTK_ADD_EXECUTABLE(dcmodify
dcmodify.cc
mdfconen.cc
mdfdsman.cc)
# make sure executables are linked to the corresponding libraries
-foreach(PROGRAM dcm2xml dcmconv dcmcrle dcmdrle dcmdump dcmgpdir dcmodify dump2dcm xml2dcm stl2dcm pdf2dcm dcm2pdf img2dcm dcm2json cda2dcm dcm2cda)
- DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmdata oflog ofstd)
+foreach(PROGRAM dcm2xml dcmconv dcmcrle dcmdrle dcmdump dcmgpdir dcmodify dump2dcm stl2dcm pdf2dcm dcm2pdf dcm2json json2dcm cda2dcm dcm2cda dcmencap dcmdecap)
+ DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmdata)
endforeach()
DCMTK_TARGET_LINK_MODULES(dcmftest ofstd)
-DCMTK_TARGET_LINK_MODULES(img2dcm i2d dcmdata)
-DCMTK_TARGET_LINK_MODULES(xml2dcm dcmxml dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(img2dcm i2d)
+DCMTK_TARGET_LINK_MODULES(xml2dcm dcmxml)
cda2dcm.o: cda2dcm.cc ../../config/include/dcmtk/config/osconfig.h \
- ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
- ../../oflog/include/dcmtk/oflog/oflog.h \
- ../../oflog/include/dcmtk/oflog/logger.h \
- ../../oflog/include/dcmtk/oflog/config.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstub.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../../oflog/include/dcmtk/oflog/config/defines.h \
- ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
- ../../oflog/include/dcmtk/oflog/loglevel.h \
- ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
- ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../../ofstd/include/dcmtk/ofstd/ofstring.h \
../../ofstd/include/dcmtk/ofstd/ofstream.h \
- ../../oflog/include/dcmtk/oflog/tchar.h \
- ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
- ../../oflog/include/dcmtk/oflog/appender.h \
- ../../ofstd/include/dcmtk/ofstd/ofmem.h \
- ../../ofstd/include/dcmtk/ofstd/ofutil.h \
../../ofstd/include/dcmtk/ofstd/oftraits.h \
- ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
- ../../oflog/include/dcmtk/oflog/layout.h \
- ../../oflog/include/dcmtk/oflog/streams.h \
- ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
- ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
- ../../oflog/include/dcmtk/oflog/spi/filter.h \
- ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
- ../../oflog/include/dcmtk/oflog/spi/logfact.h \
- ../../oflog/include/dcmtk/oflog/logmacro.h \
- ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
- ../../oflog/include/dcmtk/oflog/tracelog.h \
- ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \
- ../include/dcmtk/dcmdata/dcerror.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/ofdiag.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../include/dcmtk/dcmdata/dcistrma.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
- ../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcuid.h \
- ../include/dcmtk/dcmdata/dctagkey.h \
- ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
- ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \
- ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \
- ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \
- ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \
- ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \
- ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \
- ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \
- ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \
- ../../ofstd/include/dcmtk/ofstd/ofmap.h \
- ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \
- ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \
- ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \
- ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \
- ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \
- ../../ofstd/include/dcmtk/ofstd/ofdate.h \
- ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \
- ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
- ../../ofstd/include/dcmtk/ofstd/oftime.h \
- ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \
- ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \
- ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \
- ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \
- ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \
- ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \
- ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \
- ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \
- ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \
- ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \
- ../include/dcmtk/dcmdata/dcvrsv.h ../include/dcmtk/dcmdata/dcvruv.h \
- ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \
- ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \
- ../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
- ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcencdoc.h \
- ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
- ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
- ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
- ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
- ../../ofstd/include/dcmtk/ofstd/ofexit.h
+ ../../ofstd/include/dcmtk/ofstd/oferror.h
dcm2cda.o: dcm2cda.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstub.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h
+dcm2json.o: dcm2json.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \
../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \
../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
- ../include/dcmtk/dcmdata/cmdlnarg.h \
+ ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcjson.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../include/dcmtk/dcmdata/dcistrmz.h
-dcm2json.o: dcm2json.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/ofchrenc.h
+dcm2pdf.o: dcm2pdf.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstub.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h
+dcm2xml.o: dcm2xml.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \
../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \
../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
- ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcjson.h \
+ ../include/dcmtk/dcmdata/cmdlnarg.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
../../ofstd/include/dcmtk/ofstd/ofchrenc.h
-dcm2pdf.o: dcm2pdf.cc ../../config/include/dcmtk/config/osconfig.h \
+dcmconv.o: dcmconv.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../include/dcmtk/dcmdata/dcistrmz.h
-dcm2xml.o: dcm2xml.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmdata/dcostrmz.h ../include/dcmtk/dcmdata/dcistrmz.h \
+ ../../ofstd/include/dcmtk/ofstd/ofchrenc.h
+dcmcrle.o: dcmcrle.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../../ofstd/include/dcmtk/ofstd/ofchrenc.h
-dcmconv.o: dcmconv.cc ../../config/include/dcmtk/config/osconfig.h \
- ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
- ../../oflog/include/dcmtk/oflog/oflog.h \
- ../../oflog/include/dcmtk/oflog/logger.h \
- ../../oflog/include/dcmtk/oflog/config.h \
+ ../include/dcmtk/dcmdata/dcrleerg.h
+dcmdecap.o: dcmdecap.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcistrmz.h \
+ ../include/dcmtk/dcmdata/dcistrma.h ../include/dcmtk/dcmdata/dcxfer.h \
+ ../include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
../../oflog/include/dcmtk/oflog/config/defines.h \
../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
../../oflog/include/dcmtk/oflog/loglevel.h \
../../ofstd/include/dcmtk/ofstd/ofvector.h \
- ../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../oflog/include/dcmtk/oflog/tstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstream.h \
../../oflog/include/dcmtk/oflog/tchar.h \
../../oflog/include/dcmtk/oflog/spi/apndatch.h \
../../oflog/include/dcmtk/oflog/appender.h \
../../ofstd/include/dcmtk/ofstd/ofmem.h \
../../ofstd/include/dcmtk/ofstd/ofutil.h \
- ../../ofstd/include/dcmtk/ofstd/oftraits.h \
../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
../../oflog/include/dcmtk/oflog/layout.h \
../../oflog/include/dcmtk/oflog/streams.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
- ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \
- ../include/dcmtk/dcmdata/dcerror.h \
- ../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
- ../../ofstd/include/dcmtk/ofstd/diag/push.def \
- ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
- ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \
+ ../include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../include/dcmtk/dcmdata/dcistrma.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
- ../../ofstd/include/dcmtk/ofstd/oflimits.h \
- ../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcuid.h \
- ../include/dcmtk/dcmdata/dctagkey.h \
+ ../include/dcmtk/dcmdata/dcdocdec.h ../include/dcmtk/dcmdata/dcfilefo.h \
+ ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \
+ ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \
+ ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
- ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \
- ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \
- ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \
- ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \
- ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \
- ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \
- ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \
- ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \
- ../../ofstd/include/dcmtk/ofstd/ofmap.h \
- ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \
- ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \
- ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \
- ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \
- ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \
- ../../ofstd/include/dcmtk/ofstd/ofdate.h \
- ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \
- ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
- ../../ofstd/include/dcmtk/ofstd/oftime.h \
- ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \
- ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \
- ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \
- ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \
- ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \
- ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \
- ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \
- ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \
- ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \
- ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \
- ../include/dcmtk/dcmdata/dcvrsv.h ../include/dcmtk/dcmdata/dcvruv.h \
- ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \
- ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \
- ../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
- ../include/dcmtk/dcmdata/cmdlnarg.h \
- ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
- ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
- ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
- ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
- ../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../include/dcmtk/dcmdata/dcostrmz.h ../include/dcmtk/dcmdata/dcistrmz.h \
- ../../ofstd/include/dcmtk/ofstd/ofchrenc.h
-dcmcrle.o: dcmcrle.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
+ ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
+ ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdict.h \
+ ../include/dcmtk/dcmdata/dchashdi.h
+dcmdrle.o: dcmdrle.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../include/dcmtk/dcmdata/dcrleerg.h
-dcmdrle.o: dcmdrle.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmdata/dcrledrg.h
+dcmdump.o: dcmdump.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../../oflog/include/dcmtk/oflog/config/defines.h \
../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
../../oflog/include/dcmtk/oflog/loglevel.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../oflog/include/dcmtk/oflog/tstring.h \
../../ofstd/include/dcmtk/ofstd/ofstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstream.h \
../../oflog/include/dcmtk/oflog/tchar.h \
../../oflog/include/dcmtk/oflog/spi/apndatch.h \
../../oflog/include/dcmtk/oflog/appender.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../include/dcmtk/dcmdata/dcrledrg.h
-dcmdump.o: dcmdump.cc ../../config/include/dcmtk/config/osconfig.h \
- ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../include/dcmtk/dcmdata/dcistrmz.h \
+ ../../ofstd/include/dcmtk/ofstd/ofchrenc.h
+dcmencap.o: dcmencap.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmdata/dcencdoc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcfilefo.h \
+ ../include/dcmtk/dcmdata/dcsequen.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
+ ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../oflog/include/dcmtk/oflog/config.h \
- ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
- ../../ofstd/include/dcmtk/ofstd/ofcast.h \
- ../../ofstd/include/dcmtk/ofstd/ofexport.h \
../../oflog/include/dcmtk/oflog/config/defines.h \
../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
../../oflog/include/dcmtk/oflog/loglevel.h \
../../ofstd/include/dcmtk/ofstd/ofvector.h \
- ../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../oflog/include/dcmtk/oflog/tstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstring.h \
../../oflog/include/dcmtk/oflog/tchar.h \
../../oflog/include/dcmtk/oflog/spi/apndatch.h \
../../oflog/include/dcmtk/oflog/appender.h \
../../ofstd/include/dcmtk/ofstd/ofmem.h \
../../ofstd/include/dcmtk/ofstd/ofutil.h \
- ../../ofstd/include/dcmtk/ofstd/oftraits.h \
../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
../../oflog/include/dcmtk/oflog/layout.h \
../../oflog/include/dcmtk/oflog/streams.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
- ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \
- ../include/dcmtk/dcmdata/dcerror.h \
- ../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
- ../../ofstd/include/dcmtk/ofstd/diag/push.def \
- ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
- ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../include/dcmtk/dcmdata/dcistrma.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
- ../../ofstd/include/dcmtk/ofstd/oflimits.h \
- ../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcuid.h \
- ../include/dcmtk/dcmdata/dctagkey.h \
+ ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
- ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \
- ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \
- ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \
- ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \
- ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \
- ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \
- ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \
- ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \
- ../../ofstd/include/dcmtk/ofstd/ofmap.h \
- ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \
- ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \
- ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \
- ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \
- ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \
- ../../ofstd/include/dcmtk/ofstd/ofdate.h \
- ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \
- ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
- ../../ofstd/include/dcmtk/ofstd/oftime.h \
- ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \
- ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \
- ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \
- ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \
- ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \
- ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \
- ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \
- ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \
- ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \
- ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \
- ../include/dcmtk/dcmdata/dcvrsv.h ../include/dcmtk/dcmdata/dcvruv.h \
- ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \
- ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \
- ../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
- ../include/dcmtk/dcmdata/cmdlnarg.h \
- ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
+ ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
+ ../include/dcmtk/dcmdata/dcpcache.h \
../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
- ../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../include/dcmtk/dcmdata/dcistrmz.h \
- ../../ofstd/include/dcmtk/ofstd/ofchrenc.h
+ ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcuid.h \
+ ../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dchashdi.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h
dcmftest.o: dcmftest.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmdata/dcmetinf.h ../include/dcmtk/dcmdata/dcitem.h \
../../ofstd/include/dcmtk/ofstd/offile.h \
../include/dcmtk/dcmdata/libi2d/i2dplop.h \
../include/dcmtk/dcmdata/dcmxml/xml2dcm.h \
../include/dcmtk/dcmdata/dcmxml/dcxmldf.h
+json2dcm.o: json2dcm.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcdefine.h \
+ ../include/dcmtk/dcmdata/dcostrmz.h ../include/dcmtk/dcmdata/dcostrma.h \
+ ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcsequen.h \
+ ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \
+ ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dctag.h \
+ ../include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
+ ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
+ ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdeftag.h \
+ ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdict.h \
+ ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcjsonrd.h \
+ ../../ofstd/include/dcmtk/ofstd/ofjsmn.h
mdfconen.o: mdfconen.cc ../../config/include/dcmtk/config/osconfig.h \
mdfconen.h ../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h
pdf2dcm.o: pdf2dcm.cc ../../config/include/dcmtk/config/osconfig.h \
- ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
- ../../oflog/include/dcmtk/oflog/oflog.h \
- ../../oflog/include/dcmtk/oflog/logger.h \
- ../../oflog/include/dcmtk/oflog/config.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstub.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../../oflog/include/dcmtk/oflog/config/defines.h \
- ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
- ../../oflog/include/dcmtk/oflog/loglevel.h \
- ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
- ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../../ofstd/include/dcmtk/ofstd/ofstring.h \
../../ofstd/include/dcmtk/ofstd/ofstream.h \
- ../../oflog/include/dcmtk/oflog/tchar.h \
- ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
- ../../oflog/include/dcmtk/oflog/appender.h \
- ../../ofstd/include/dcmtk/ofstd/ofmem.h \
- ../../ofstd/include/dcmtk/ofstd/ofutil.h \
../../ofstd/include/dcmtk/ofstd/oftraits.h \
- ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
- ../../oflog/include/dcmtk/oflog/layout.h \
- ../../oflog/include/dcmtk/oflog/streams.h \
- ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
- ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
- ../../oflog/include/dcmtk/oflog/spi/filter.h \
- ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
- ../../oflog/include/dcmtk/oflog/spi/logfact.h \
- ../../oflog/include/dcmtk/oflog/logmacro.h \
- ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
- ../../oflog/include/dcmtk/oflog/tracelog.h \
- ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \
- ../include/dcmtk/dcmdata/dcerror.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/ofdiag.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../include/dcmtk/dcmdata/dcistrma.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
- ../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcuid.h \
- ../include/dcmtk/dcmdata/dctagkey.h \
- ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
- ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \
- ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \
- ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \
- ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \
- ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \
- ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \
- ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \
- ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \
- ../../ofstd/include/dcmtk/ofstd/ofmap.h \
- ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \
- ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \
- ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \
- ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \
- ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \
- ../../ofstd/include/dcmtk/ofstd/ofdate.h \
- ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \
- ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
- ../../ofstd/include/dcmtk/ofstd/oftime.h \
- ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \
- ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \
- ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \
- ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \
- ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \
- ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \
- ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \
- ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \
- ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \
- ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \
- ../include/dcmtk/dcmdata/dcvrsv.h ../include/dcmtk/dcmdata/dcvruv.h \
- ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \
- ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \
- ../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
- ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcencdoc.h \
- ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
- ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
- ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
- ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
- ../../ofstd/include/dcmtk/ofstd/ofexit.h
+ ../../ofstd/include/dcmtk/ofstd/oferror.h
stl2dcm.o: stl2dcm.cc ../../config/include/dcmtk/config/osconfig.h \
- ../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
- ../../oflog/include/dcmtk/oflog/oflog.h \
- ../../oflog/include/dcmtk/oflog/logger.h \
- ../../oflog/include/dcmtk/oflog/config.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstub.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../../oflog/include/dcmtk/oflog/config/defines.h \
- ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
- ../../oflog/include/dcmtk/oflog/loglevel.h \
- ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
- ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../../ofstd/include/dcmtk/ofstd/ofstring.h \
../../ofstd/include/dcmtk/ofstd/ofstream.h \
- ../../oflog/include/dcmtk/oflog/tchar.h \
- ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
- ../../oflog/include/dcmtk/oflog/appender.h \
- ../../ofstd/include/dcmtk/ofstd/ofmem.h \
- ../../ofstd/include/dcmtk/ofstd/ofutil.h \
../../ofstd/include/dcmtk/ofstd/oftraits.h \
- ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
- ../../oflog/include/dcmtk/oflog/layout.h \
- ../../oflog/include/dcmtk/oflog/streams.h \
- ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
- ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
- ../../oflog/include/dcmtk/oflog/spi/filter.h \
- ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
- ../../oflog/include/dcmtk/oflog/spi/logfact.h \
- ../../oflog/include/dcmtk/oflog/logmacro.h \
- ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
- ../../oflog/include/dcmtk/oflog/tracelog.h \
- ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcswap.h \
- ../include/dcmtk/dcmdata/dcerror.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/ofdiag.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../include/dcmtk/dcmdata/dcistrma.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
- ../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dcostrma.h ../include/dcmtk/dcmdata/dcuid.h \
- ../include/dcmtk/dcmdata/dctagkey.h \
- ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
- ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcdicent.h \
- ../include/dcmtk/dcmdata/dchashdi.h ../include/dcmtk/dcmdata/dcdict.h \
- ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcobject.h \
- ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dcelem.h \
- ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dclist.h \
- ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \
- ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcsequen.h \
- ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcdicdir.h \
- ../../ofstd/include/dcmtk/ofstd/ofmap.h \
- ../include/dcmtk/dcmdata/dcdirrec.h ../include/dcmtk/dcmdata/dcvrulup.h \
- ../include/dcmtk/dcmdata/dcvrul.h ../include/dcmtk/dcmdata/dcpixseq.h \
- ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcbytstr.h \
- ../include/dcmtk/dcmdata/dcvrae.h ../include/dcmtk/dcmdata/dcvras.h \
- ../include/dcmtk/dcmdata/dcvrcs.h ../include/dcmtk/dcmdata/dcvrda.h \
- ../../ofstd/include/dcmtk/ofstd/ofdate.h \
- ../include/dcmtk/dcmdata/dcvrds.h ../include/dcmtk/dcmdata/dcvrdt.h \
- ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
- ../../ofstd/include/dcmtk/ofstd/oftime.h \
- ../include/dcmtk/dcmdata/dcvris.h ../include/dcmtk/dcmdata/dcvrtm.h \
- ../include/dcmtk/dcmdata/dcvrui.h ../include/dcmtk/dcmdata/dcvrur.h \
- ../include/dcmtk/dcmdata/dcchrstr.h ../include/dcmtk/dcmdata/dcvrlo.h \
- ../include/dcmtk/dcmdata/dcvrlt.h ../include/dcmtk/dcmdata/dcvrpn.h \
- ../include/dcmtk/dcmdata/dcvrsh.h ../include/dcmtk/dcmdata/dcvrst.h \
- ../include/dcmtk/dcmdata/dcvruc.h ../include/dcmtk/dcmdata/dcvrut.h \
- ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpixel.h \
- ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcovlay.h \
- ../include/dcmtk/dcmdata/dcvrat.h ../include/dcmtk/dcmdata/dcvrss.h \
- ../include/dcmtk/dcmdata/dcvrus.h ../include/dcmtk/dcmdata/dcvrsl.h \
- ../include/dcmtk/dcmdata/dcvrsv.h ../include/dcmtk/dcmdata/dcvruv.h \
- ../include/dcmtk/dcmdata/dcvrfl.h ../include/dcmtk/dcmdata/dcvrfd.h \
- ../include/dcmtk/dcmdata/dcvrof.h ../include/dcmtk/dcmdata/dcvrod.h \
- ../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
- ../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcencdoc.h \
- ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
- ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
- ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
- ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
- ../../ofstd/include/dcmtk/ofstd/ofexit.h
+ ../../ofstd/include/dcmtk/ofstd/oferror.h
xml2dcm.o: xml2dcm.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmdata/dctk.h ../include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
objs = dcmftest.o dcmconv.o dcmdump.o dump2dcm.o dcmgpdir.o dcm2xml.o \
xml2dcm.o dcmcrle.o dcmdrle.o dcmodify.o mdfdsman.o mdfconen.o \
- cda2dcm.o stl2dcm.o pdf2dcm.o dcm2pdf.o dcm2cda.o img2dcm.o dcm2json.o
+ cda2dcm.o stl2dcm.o pdf2dcm.o dcm2pdf.o dcm2cda.o img2dcm.o dcm2json.o \
+ json2dcm.o dcmencap.o dcmdecap.o
progs = dcmftest dcmconv dcmdump dump2dcm dcmgpdir dcm2xml xml2dcm dcmcrle \
- dcmdrle dcmodify pdf2dcm stl2dcm cda2dcm dcm2pdf dcm2cda img2dcm dcm2json
+ dcmdrle dcmodify pdf2dcm stl2dcm cda2dcm dcm2pdf dcm2cda img2dcm dcm2json \
+ json2dcm dcmencap dcmdecap
all: $(progs)
dcm2json: dcm2json.o
$(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS)
+json2dcm: json2dcm.o
+ $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS)
+
+dcmencap: dcmencap.o
+ $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS)
+
+dcmdecap: dcmdecap.o
+ $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS)
+
install: all
$(configdir)/mkinstalldirs $(DESTDIR)$(bindir)
/*
*
- * Copyright (C) 2018-2019, OFFIS e.V.
+ * Copyright (C) 2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* Module: dcmdata
*
- * Author: Pedro Arizpe
+ * Authors: Marco Eichelberg
*
- * Purpose: Encapsulate CDA file into a DICOM file
+ * Purpose: Proxy stub that calls dcmencap
*
*/
-#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first*/
-#include "dcmtk/dcmdata/dctk.h"
-#include "dcmtk/dcmdata/dcencdoc.h"
-#include "dcmtk/ofstd/ofconapp.h"
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/ofstub.h"
+#include "dcmtk/ofstd/ofstd.h"
+#include <cstring>
-#ifdef WITH_ZLIB
-#include <zlib.h> /* for zlibVersion() */
-#endif
-
-#define OFFIS_CONSOLE_APPLICATION "cda2dcm"
-
-static OFLogger cda2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
-
-static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
-OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
-
-int main(int argc, char *argv[])
+int main(int argc, char** argv)
{
- OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encapsulate CDA file into DICOM format", rcsid);
- OFCommandLine cmd;
- int errorCode = EXITCODE_NO_ERROR;
- OFCondition result = EC_Normal;
- DcmFileFormat fileformat;
- DcmEncapsulatedDocument encapsulator;
- OFLOG_TRACE(cda2dcmLogger, "Including necessary options");
- encapsulator.addCDACommandlineOptions(cmd);
- OFLOG_TRACE(cda2dcmLogger, "Evaluating command line");
- prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
-
- if (app.parseCommandLine(cmd, argc, argv)) {
- OFLOG_TRACE (cda2dcmLogger, "Checking exclusive options first");
- if (cmd.hasExclusiveOption())
+ // create an argv array that is one entry larger than the one specified by the user
+ char **my_argv = new char *[argc+2];
+ char filetype[100];
+ OFStandard::strlcpy(filetype, "--filetype-cda", sizeof(filetype));
+
+ // copy arguments, then add file type argument and NULL pointer
+ memcpy(my_argv, argv, argc * sizeof(char *));
+ my_argv[argc] = filetype;
+ my_argv[argc+1] = NULL;
+
+ // call stub
+ int result;
+ if (argc == 1)
{
- if (cmd.findOption("--version"))
- {
- app.printHeader(OFTrue /*print host identifier*/);
- COUT << OFendl << "External libraries used: ";
-#ifdef WITH_ZLIB
- COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
-#else
- COUT << " none" << OFendl;
-#endif
- return EXITCODE_NO_ERROR;
- }
+ // no command line arguments given. Just forward call.
+ result = OFstub_main(argc, argv, "cda2dcm", "dcmencap");
+ }
+ else
+ {
+ // Forward call with additional command line argument.
+ result = OFstub_main(argc+1, my_argv, "cda2dcm", "dcmencap");
}
- encapsulator.parseArguments(app, cmd);
- }
- //print resource identifier
- OFLOG_DEBUG(cda2dcmLogger, rcsid << OFendl);
-
- OFLOG_DEBUG(cda2dcmLogger, "making sure data dictionary is loaded");
- if (!dcmDataDict.isDictionaryLoaded())
- {
- OFLOG_WARN(cda2dcmLogger, "no data dictionary loaded, check environment variable: "
- << DCM_DICT_ENVIRONMENT_VARIABLE);
- }
- OFLOG_TRACE(cda2dcmLogger, "Creating identifiers (and reading series data)");
- result = encapsulator.createIdentifiers(cda2dcmLogger);
- if (result.bad())
- {
- OFLOG_FATAL(cda2dcmLogger, "There was an error while reading the series data");
- return EXITCODE_INVALID_INPUT_FILE;
- }
- OFLOG_DEBUG(cda2dcmLogger, "Fetching CDA Data");
- errorCode = encapsulator.getCDAData(encapsulator.getInputFileName().c_str(), cda2dcmLogger);
- if (errorCode != EXITCODE_NO_ERROR)
- {
- OFLOG_ERROR(cda2dcmLogger, "There was a problem with the CDA File");
- return errorCode;
- }
- else
- {
- OFLOG_INFO(cda2dcmLogger, "creating encapsulated CDA object");
- errorCode = encapsulator.insertEncapsulatedDocument(fileformat.getDataset(), cda2dcmLogger);
- }
- if (errorCode != EXITCODE_NO_ERROR)
- {
- OFLOG_ERROR(cda2dcmLogger, "unable to create CDA encapsulation to DICOM format");
- return errorCode;
- }
- OFLOG_INFO(cda2dcmLogger, "Generating an instance number that is guaranteed to be unique within a series.");
- result = encapsulator.createHeader(fileformat.getDataset(), cda2dcmLogger);
- if (result.bad())
- {
- OFLOG_ERROR(cda2dcmLogger, "unable to create DICOM header: " << result.text());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
- OFLOG_INFO(cda2dcmLogger, "writing encapsulated CDA object as file " << encapsulator.getOutputFileName());
-
- OFLOG_INFO(cda2dcmLogger, "Check if new output transfer syntax is possible");
-
- DcmXfer opt_oxferSyn(encapsulator.getTransferSyntax());
-
- fileformat.getDataset()->chooseRepresentation(encapsulator.getTransferSyntax(), NULL);
- if (fileformat.getDataset()->canWriteXfer(encapsulator.getTransferSyntax()))
- {
- OFLOG_INFO(cda2dcmLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written");
- }
- else {
- OFLOG_ERROR(cda2dcmLogger, "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- OFLOG_INFO(cda2dcmLogger, "Checking for DICOM key overriding");
- result = encapsulator.applyOverrideKeys(fileformat.getDataset());
- if (result.bad())
- {
- OFLOG_ERROR(cda2dcmLogger, "There was a problem while overriding a key:" << OFendl
- << result.text());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
- OFLOG_INFO(cda2dcmLogger, "write converted DICOM file with metaheader");
- result = encapsulator.saveFile(fileformat);
- if (result.bad())
- {
- OFLOG_ERROR(cda2dcmLogger, result.text() << ": writing file: " << encapsulator.getOutputFileName());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- OFLOG_INFO(cda2dcmLogger, "CDA encapsulation successful");
- return EXITCODE_NO_ERROR;
+ // clean up (Windows only, on Posix systems the stub will not return)
+ delete[] my_argv;
+ return result;
}
/*
*
- * Copyright (C) 2023-2024, OFFIS e.V.
+ * Copyright (C) 2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* Module: dcmdata
*
- * Author: Tingyan Xu
+ * Authors: Marco Eichelberg
*
- * Purpose: Extract CDA file from DICOM encapsulated CDA storage object
+ * Purpose: Proxy stub that calls dcmdecap
*
*/
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/ofstub.h"
-#include "dcmtk/dcmdata/dctk.h"
-#include "dcmtk/dcmdata/cmdlnarg.h"
-#include "dcmtk/ofstd/ofconapp.h"
-#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */
-#include "dcmtk/ofstd/ofstd.h"
-#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */
-
-#ifdef WITH_ZLIB
-#include <zlib.h> /* for zlibVersion() */
-#endif
-
-#define OFFIS_CONSOLE_APPLICATION "dcm2cda"
-
-static OFLogger dcm2cdaLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
-
-static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
-OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
-
-#define SHORTCOL 3
-#define LONGCOL 20
-
-void addInputOptions(OFCommandLine& cmd)
-{
- cmd.addGroup("input options:");
- cmd.addSubGroup("input file format:");
- cmd.addOption("--read-file", "+f", "read file format or data set (default)");
- cmd.addOption("--read-file-only", "+fo", "read file format only");
- cmd.addOption("--read-dataset", "-f", "read data set without file meta information");
-
- cmd.addSubGroup("input transfer syntax:");
- cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)");
- cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header");
- cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS");
- cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS");
- cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS");
-
- cmd.addSubGroup("parsing of odd-length attributes:");
- cmd.addOption("--accept-odd-length", "+ao", "accept odd length attributes (default)");
- cmd.addOption("--assume-even-length", "+ae", "assume real length is one byte larger");
-
- cmd.addSubGroup("handling of undefined length UN elements:");
- cmd.addOption("--enable-cp246", "+ui", "read undefined len UN as implicit VR (default)");
- cmd.addOption("--disable-cp246", "-ui", "read undefined len UN as explicit VR");
-
- cmd.addSubGroup("handling of defined length UN elements:");
- cmd.addOption("--retain-un", "-uc", "retain elements as UN (default)");
- cmd.addOption("--convert-un", "+uc", "convert to real VR if known");
-
- cmd.addSubGroup("automatic data correction:");
- cmd.addOption("--enable-correction", "+dc", "enable automatic data correction (default)");
- cmd.addOption("--disable-correction", "-dc", "disable automatic data correction");
-
-#ifdef WITH_ZLIB
- cmd.addSubGroup("bitstream format of deflated input:");
- cmd.addOption("--bitstream-deflated", "+bd", "expect deflated bitstream (default)");
- cmd.addOption("--bitstream-zlib", "+bz", "expect deflated zlib bitstream");
-#endif
-}
-
-void addDCM2CDACommandlineOptions(OFCommandLine& cmd)
-{
- cmd.setOptionColumns(LONGCOL, SHORTCOL);
- cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
-
- cmd.addParam("dcmfile-in", "DICOM input filename (\"-\" for stdin)");
- cmd.addParam("cdafile-out", "CDA output filename");
-
- cmd.addGeneralOptions(LONGCOL, SHORTCOL);
- OFLog::addOptions(cmd);
- addInputOptions(cmd);
-}
-
-/**
- * function for parsing commandline arguments
- */
-void parseArguments(OFConsoleApplication& app, OFCommandLine& cmd,
- E_FileReadMode& opt_readMode, E_TransferSyntax& opt_ixfer,
- const char*& opt_ifname,
- const char*& opt_ofname
-)
-{
- cmd.getParam(1, opt_ifname);
- cmd.getParam(2, opt_ofname);
-
- OFLog::configureFromCommandLine(cmd, app);
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--read-file"))
- {
- opt_readMode = ERM_autoDetect;
- }
- if (cmd.findOption("--read-file-only"))
- {
- opt_readMode = ERM_fileOnly;
- }
- if (cmd.findOption("--read-dataset"))
- {
- opt_readMode = ERM_dataset;
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--read-xfer-auto"))
- {
- opt_ixfer = EXS_Unknown;
- }
- if (cmd.findOption("--read-xfer-detect"))
- {
- dcmAutoDetectDatasetXfer.set(OFTrue);
- }
- if (cmd.findOption("--read-xfer-little"))
- {
- app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset);
- opt_ixfer = EXS_LittleEndianExplicit;
- }
- if (cmd.findOption("--read-xfer-big"))
- {
- app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset);
- opt_ixfer = EXS_BigEndianExplicit;
- }
- if (cmd.findOption("--read-xfer-implicit"))
- {
- app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset);
- opt_ixfer = EXS_LittleEndianImplicit;
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--accept-odd-length"))
- {
- dcmAcceptOddAttributeLength.set(OFTrue);
- }
- if (cmd.findOption("--assume-even-length"))
- {
- dcmAcceptOddAttributeLength.set(OFFalse);
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--enable-cp246"))
- {
- dcmEnableCP246Support.set(OFTrue);
- }
- if (cmd.findOption("--disable-cp246"))
- {
- dcmEnableCP246Support.set(OFFalse);
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--retain-un"))
- {
- dcmEnableUnknownVRConversion.set(OFFalse);
- }
- if (cmd.findOption("--convert-un"))
- {
- dcmEnableUnknownVRConversion.set(OFTrue);
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--enable-correction"))
- {
- dcmEnableAutomaticInputDataCorrection.set(OFTrue);
- }
- if (cmd.findOption("--disable-correction"))
- {
- dcmEnableAutomaticInputDataCorrection.set(OFFalse);
- }
- cmd.endOptionBlock();
-
-#ifdef WITH_ZLIB
- cmd.beginOptionBlock();
- if (cmd.findOption("--bitstream-deflated"))
- {
- dcmZlibExpectRFC1950Encoding.set(OFFalse);
- }
- if (cmd.findOption("--bitstream-zlib"))
- {
- dcmZlibExpectRFC1950Encoding.set(OFTrue);
- }
- cmd.endOptionBlock();
-#endif
-}
-
-int main(int argc, char* argv[])
+int main(int argc, char** argv)
{
- const char* opt_ifname = NULL;
- const char* opt_ofname = NULL;
- E_FileReadMode opt_readMode = ERM_autoDetect;
- E_TransferSyntax opt_ixfer = EXS_Unknown;
-
- OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Extract CDA file from DICOM encapsulated CDA", rcsid);
- OFCommandLine cmd;
-
- // necessary options
- addDCM2CDACommandlineOptions(cmd);
-
- // evaluating command line
- prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
- if (app.parseCommandLine(cmd, argc, argv))
- {
- // checking exclusive options first
- if (cmd.hasExclusiveOption())
- {
- if (cmd.findOption("--version"))
- {
- app.printHeader(OFTrue /*print host identifier*/);
- COUT << OFendl << "External libraries used:";
-#ifdef WITH_ZLIB
- COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
-#else
- COUT << " none" << OFendl;
-#endif
- return EXITCODE_NO_ERROR;
- }
- }
-
- /* command line parameters and options */
- parseArguments(app, cmd, opt_readMode, opt_ixfer, opt_ifname, opt_ofname);
- }
-
- /* print resource identifier */
- OFLOG_DEBUG(dcm2cdaLogger, rcsid << OFendl);
-
- OFLOG_DEBUG(dcm2cdaLogger, "making sure data dictionary is loaded");
- if (!dcmDataDict.isDictionaryLoaded())
- {
- OFLOG_WARN(dcm2cdaLogger, "no data dictionary loaded, check environment variable: "
- << DCM_DICT_ENVIRONMENT_VARIABLE);
- }
-
- // open input file
- if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0))
- {
- OFLOG_ERROR(dcm2cdaLogger, "invalid filename: <empty string>");
- return EXITCODE_NO_INPUT_FILES;
- }
-
- OFCondition cond = EC_Normal;
-
- DcmFileFormat dfile;
- DcmDataset* dataset = dfile.getDataset();
-
- OFLOG_INFO(dcm2cdaLogger, "open input file " << opt_ifname);
- /* load file to dfile, using given transfer syntax and other variables */
- cond = dfile.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);
- if (cond.bad())
- {
- OFLOG_ERROR(dcm2cdaLogger, cond.text() << ": reading file: " << opt_ifname);
- return EXITCODE_CANNOT_READ_INPUT_FILE;
- }
-
- /* check SOP */
- OFString sopClass;
- cond = dataset->findAndGetOFString(DCM_SOPClassUID, sopClass);
- if (cond.bad() || sopClass != UID_EncapsulatedCDAStorage)
- {
- OFLOG_ERROR(dcm2cdaLogger, "SOPClassUID not of SOP UID_EncapsulatedCDAStorage: " << opt_ifname);
- return EXITCODE_INVALID_INPUT_FILE;
- }
-
- /* get EncapsulatedDocument */
- Uint8* cdaDocument = NULL;
- unsigned long int delemlen = 0;
- cond = dataset->findAndGetUint8Array(DCM_EncapsulatedDocument, (const Uint8*&)cdaDocument, &delemlen);
- if (cond.bad() || cdaDocument == NULL || delemlen == 0)
- {
- OFLOG_ERROR(dcm2cdaLogger, "EncapsulatedDocument missing or has the wrong VR");
- return EXITCODE_INVALID_INPUT_FILE;
- }
-
- /* get and check element Encapsulated Document Length */
- Uint32 lenElem;
- cond = dataset->findAndGetUint32(DCM_EncapsulatedDocumentLength, lenElem);
- /* EncapsulatedDocumentLength Element is invalid or
- * it does not fit the length of the encapsulated document
- * (it has to be equal or equal to EncapsulatedDocumentLength -1)
- */
- if (cond.bad() || (lenElem != delemlen && lenElem != delemlen - 1))
- {
- OFLOG_DEBUG(dcm2cdaLogger, "EncapsulatedDocumentLength missing or invalid, "
- "using length of EncapsulatedDocument");
- lenElem = delemlen;
- /* Strip pad byte at end of file, if there is one.
- * CDA documents end with a closing XML tag, optionally followed by whitespace.
- * If the last character of the file is not a CR ('\r', 13) or LF ('\n', 10), and not the
- * letter '>', we assume it is either trailing garbage or a pad byte, and remove it.
- */
- if (cdaDocument[lenElem - 1] != '\n' && cdaDocument[lenElem - 1] != '\r' && cdaDocument[lenElem - 1] != '>')
- {
- OFLOG_DEBUG(dcm2cdaLogger, "removing the pad byte at end of EncapsulatedDocument");
- --lenElem;
- }
- }
-
- OFLOG_INFO(dcm2cdaLogger, "writing CDA file to " << opt_ofname);
- FILE* cdafile = fopen(opt_ofname, "wb");
- if (cdafile == NULL)
- {
- OFLOG_ERROR(dcm2cdaLogger, "unable to create file " << opt_ofname);
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- if (lenElem != fwrite(cdaDocument, 1, lenElem, cdafile))
- {
- OFLOG_ERROR(dcm2cdaLogger, "write error in file " << opt_ofname);
- fclose(cdafile);
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- if(fclose(cdafile))
- {
- OFLOG_FATAL(dcm2cdaLogger, "write error in file " << opt_ofname);
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- OFLOG_INFO(dcm2cdaLogger, "conversion successful");
-
- return EXITCODE_NO_ERROR;
+ // call stub. Will not return on Posix systems.
+ return OFstub_main(argc, argv, "dcm2cda", "dcmdecap");
}
/*
-*
-* Copyright (C) 2016-2022, OFFIS e.V.
-* All rights reserved. See COPYRIGHT file for details.
-*
-* This software and supporting documentation were developed by
-*
-* OFFIS e.V.
-* R&D Division Health
-* Escherweg 2
-* D-26121 Oldenburg, Germany
-*
-*
-* Module: dcmdata
-*
-* Author: Sebastian Grallert
-*
-* Purpose: Convert the contents of a DICOM file to JSON format
-*
-*/
+ *
+ * Copyright (C) 2016-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Sebastian Grallert, Marco Eichelberg
+ *
+ * Purpose: Convert the contents of a DICOM file to JSON format
+ *
+ */
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/ofstream.h"
#include "dcmtk/ofstd/ofconapp.h"
#include "dcmtk/ofstd/ofexit.h"
+#include "dcmtk/ofstd/ofstd.h"
+
+#include <cstdlib>
#ifdef WITH_ZLIB
#include <zlib.h> /* for zlibVersion() */
#ifdef DCMTK_ENABLE_CHARSET_CONVERSION
#include "dcmtk/ofstd/ofchrenc.h" /* for OFCharacterEncoding */
#endif
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
#define OFFIS_CONSOLE_APPLICATION "dcm2json"
#define OFFIS_CONSOLE_DESCRIPTION "Convert DICOM file and data set to JSON"
#define EXITCODE_CANNOT_CONVERT_TO_UNICODE 80
#define EXITCODE_CANNOT_WRITE_VALID_JSON 81
+#define DCM2JSON_WELL_KNOWN_UID "1.2.276.0.7230010.3.1.4.1787205428.3192777.1748004619.679033"
+
static OFLogger dcm2jsonLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
// ********************************************
-/* Function to call all writeJson() functions in DCMTK */
-static OFCondition writeFile(STD_NAMESPACE ostream &out,
- const char *ifname,
+/** Convert a DICOM file to JSON.
+ * @param out output stream to write JSON to
+ * @param dfile pointer to the DICOM object, must not be NULL
+ * @param readMode mode used to read the file. Determines whether conversion
+ * takes place at DcmFileFormat or DcmDataset level.
+ * @param format OFTrue for pretty printing, OFFalse for compact code
+ * @param printMetaInfo If true, the meta-header attributes are also converted
+ * to JSON as a non-standard DCMTK extension
+ * @param encode_extended enables an extension of the JSON syntax to permit
+ * "-inf", "nan" and "inf" to be generated for infinity and not-a-number values
+ * @param opt_ns_policy policy for converting IS/DS values to JSON
+ * @param min_bulk_size minimum size for bulk data, negative number to disable bulk data
+ * @param bulk_uri_prefix prefix string for bulk data URIs
+ * @param bulk_dir directory to which bulk data should be written
+ * @return EC_Normal if successful, and error code otherwise
+ */
+static OFCondition writeFile(
+ STD_NAMESPACE ostream &out,
DcmFileFormat *dfile,
const E_FileReadMode readMode,
const OFBool format,
const OFBool printMetaInfo,
const OFBool encode_extended,
- const DcmJsonFormat::NumStringPolicy opt_ns_policy)
+ const DcmJsonFormat::NumStringPolicy opt_ns_policy,
+ const OFCmdSignedInt min_bulk_size,
+ const char *bulk_uri_prefix,
+ const char *bulk_dir)
{
OFCondition result = EC_IllegalParameter;
- if ((ifname != NULL) && (dfile != NULL))
+ if (dfile != NULL)
{
/* write JSON document content */
DcmDataset *dset = dfile->getDataset();
DcmJsonFormatPretty fmt(printMetaInfo);
fmt.setJsonExtensionEnabled(encode_extended);
fmt.setJsonNumStringPolicy(opt_ns_policy);
+ fmt.setMinBulkSize(OFstatic_cast(ssize_t, min_bulk_size));
+ fmt.setBulkURIPrefix(bulk_uri_prefix);
+ fmt.setBulkDir(bulk_dir);
if (readMode == ERM_dataset)
result = dset->writeJsonExt(out, fmt, OFTrue, OFTrue);
else result = dfile->writeJson(out, fmt);
DcmJsonFormatCompact fmt(printMetaInfo);
fmt.setJsonExtensionEnabled(encode_extended);
fmt.setJsonNumStringPolicy(opt_ns_policy);
+ fmt.setMinBulkSize(OFstatic_cast(ssize_t, min_bulk_size));
+ fmt.setBulkURIPrefix(bulk_uri_prefix);
+ fmt.setBulkDir(bulk_dir);
if (readMode == ERM_dataset)
result = dset->writeJsonExt(out, fmt, OFTrue, OFTrue);
else result = dfile->writeJson(out, fmt);
return result;
}
+/** append the given file path to the output URL while URL-encoding
+ * special characters. Note that the reserved characters '/' and
+ * ':' are not encoding since they are routinely used in file: URLs.
+ * @param path file path
+ * @param output_url output URL
+ */
+static void appendURLEncodedPath(const char *path, OFString& output_url)
+{
+ if (path)
+ {
+ char c;
+ for (const char *p=path; *p != '\0'; ++p)
+ {
+ c = *p;
+ // URL encode all characters except a-z, A-Z, 0-9, and "-_./!~$:"
+ // The reserved characters "/" and ":" are not URL encoded because they routinely occur in file: URLs
+ if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '/' || c == '!' || c == '~' || c == '$' || c == ':') output_url.append(1, *p);
+ else if (c == '\\')
+ {
+ // convert backslashes to forward slashes
+ output_url.append("/");
+ }
+ else
+ {
+ char buf[5];
+ OFStandard::snprintf(buf, 5, "%%%02X", c);
+ output_url.append(buf);
+ }
+ }
+ }
+}
+
+/** determine the real path to the given working directory
+ * and return it in the form of a file:// URI.
+ * @param input_dir current working directory, NULL for current directory
+ * @param output_dir file URI to real path (without symbolic links) returned in this parameter if successful
+ * @return EC_Normal if successful, and error code otherwise
+ */
+static OFCondition getCurrentWorkingDir(const char *input_dir, OFString& output_dir)
+{
+ // if dir is empty, assume current directory
+ if (input_dir == NULL) input_dir = ".";
+
+#ifdef HAVE_WINDOWS_H
+ char *resolved_path = _fullpath(NULL, input_dir, 0);
+#else
+ char *resolved_path = realpath(input_dir, NULL);
+#endif
+ if (resolved_path == NULL)
+ {
+ OFLOG_ERROR(dcm2jsonLogger, OFFIS_CONSOLE_APPLICATION << ": Cannot create or determine bulk data directory");
+ return EC_DirectoryDoesNotExist;
+ }
+ output_dir = "file://localhost";
+ if (resolved_path[0] != '/') output_dir.append("/");
+ appendURLEncodedPath(resolved_path, output_dir);
+ output_dir.append("/");
+ free(resolved_path);
+ return EC_Normal;
+}
+
#define SHORTCOL 3
#define LONGCOL 20
E_TransferSyntax opt_ixfer = EXS_Unknown;
OFString optStr;
+ OFCmdSignedInt opt_min_bulk_size = -1;
+ const char *opt_bulk_uri_prefix = NULL;
+ const char *opt_bulk_dir = ".";
+ OFBool opt_bulk_subdir = OFFalse;
+ OFString bulkURIPrefix;
+
OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, OFFIS_CONSOLE_DESCRIPTION, rcsid);
OFCommandLine cmd;
cmd.setOptionColumns(LONGCOL, SHORTCOL);
cmd.addGroup("input options:");
cmd.addSubGroup("input file format:");
- cmd.addOption("--read-file", "+f", "read file format or data set (default)");
- cmd.addOption("--read-file-only", "+fo", "read file format only");
- cmd.addOption("--read-dataset", "-f", "read data set without file meta information");
+ cmd.addOption("--read-file", "+f", "read file format or data set (default)");
+ cmd.addOption("--read-file-only", "+fo", "read file format only");
+ cmd.addOption("--read-dataset", "-f", "read data set without file meta information");
cmd.addSubGroup("input transfer syntax:");
- cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)");
- cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header");
- cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS");
- cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS");
- cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS");
+ cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)");
+ cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header");
+ cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS");
+ cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS");
+ cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS");
cmd.addGroup("processing options:");
cmd.addSubGroup("encoding of infinity and not-a-number:");
- cmd.addOption("--encode-strict", "-es", "report error for 'inf' and 'nan' (default)");
- cmd.addOption("--encode-extended", "-ee", "permit 'inf' and 'nan' in JSON numbers");
+ cmd.addOption("--encode-strict", "-es", "report error for 'inf' and 'nan' (default)");
+ cmd.addOption("--encode-extended", "-ee", "permit 'inf' and 'nan' in JSON numbers");
cmd.addSubGroup("encoding of IS and DS (integer/decimal string) elements:");
- cmd.addOption("--is-ds-auto", "-ia", "encode as number if valid, as string\notherwise (default)");
- cmd.addOption("--is-ds-num", "-in", "always encode as number, fail if invalid");
- cmd.addOption("--is-ds-string", "-is", "always encode as string");
+ cmd.addOption("--is-ds-auto", "-ia", "encode as number if valid, as string\notherwise (default)");
+ cmd.addOption("--is-ds-num", "-in", "always encode as number, fail if invalid");
+ cmd.addOption("--is-ds-string", "-is", "always encode as string");
+ cmd.addSubGroup("bulk data URI options:");
+ cmd.addOption("--bulk-disabled", "-b", "write everything as inline binary (default)");
+ cmd.addOption("--bulk-enabled", "+b", "write large attributes as bulk data");
+ cmd.addOption("--bulk-size", "+bz", 1, "[s]ize: integer (default: 1)", "use bulk data for attributes >= s kBytes");
+ cmd.addOption("--bulk-uri-prefix", "+bp", 1, "[u]ri prefix: string", "use prefix u when generating bulk data URIs\n(default: file URI)");
+ cmd.addOption("--bulk-dir", "+bd", 1, "[d]irectory: string", "write bulk data files to d (default: '.')");
+ cmd.addOption("--bulk-subdir", "+bs", "create subdirectory for each SOP instance\n(default: no subdirectory)");
cmd.addGroup("output options:");
cmd.addSubGroup("output format:");
- cmd.addOption("--formatted-code", "+fc", "enable whitespace formatting (default)");
- cmd.addOption("--compact-code", "-fc", "print only required characters");
- cmd.addOption("--write-meta", "+m", "write data set with meta information\n(warning: not conforming to the DICOM standard)");
+ cmd.addOption("--formatted-code", "+fc", "enable whitespace formatting (default)");
+ cmd.addOption("--compact-code", "-fc", "print only required characters");
+ cmd.addOption("--write-meta", "+m", "write data set with meta information\n(warning: not conforming to the DICOM standard)");
/* evaluate command line */
prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
opt_ns_policy = DcmJsonFormat::NSP_always_string;
cmd.endOptionBlock();
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--bulk-disabled"))
+ opt_min_bulk_size = -1;
+ if (cmd.findOption("--bulk-enabled"))
+ opt_min_bulk_size = 1;
+ cmd.endOptionBlock();
+
+ if (cmd.findOption("--bulk-size"))
+ {
+ app.checkDependence("--bulk-size", "--bulk-enabled", opt_min_bulk_size >= 0);
+ app.checkValue(cmd.getValueAndCheckMin(opt_min_bulk_size, 0));
+ }
+
+ if (cmd.findOption("--bulk-uri-prefix"))
+ {
+ app.checkDependence("--bulk-uri-prefix", "--bulk-enabled", opt_min_bulk_size >= 0);
+ app.checkValue(cmd.getValue(opt_bulk_uri_prefix));
+ }
+
+ if (cmd.findOption("--bulk-dir"))
+ {
+ app.checkDependence("--bulk-dir", "--bulk-enabled", opt_min_bulk_size >= 0);
+ app.checkValue(cmd.getValue(opt_bulk_dir));
+ }
+
+ if (cmd.findOption("--bulk-subdir"))
+ {
+ app.checkDependence("--bulk-subdir", "--bulk-enabled", opt_min_bulk_size >= 0);
+ opt_bulk_subdir = OFTrue;
+ }
+
/* format options */
cmd.beginOptionBlock();
if (cmd.findOption("--formatted-code"))
<< DCM_DICT_ENVIRONMENT_VARIABLE);
}
+ OFCondition status;
+ if ((opt_min_bulk_size >= 0) && (opt_bulk_uri_prefix == NULL))
+ {
+ // try to create bulk directory, ignore failure
+ (void) OFStandard::createDirectory(opt_bulk_dir, "");
+
+ // determine default Bulk URI prefix
+ status = getCurrentWorkingDir(opt_bulk_dir, bulkURIPrefix);
+ if (status.bad())
+ {
+ return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+ }
+ opt_bulk_uri_prefix = bulkURIPrefix.c_str();
+ }
+
int result = 0;
/* first parameter is treated as the input filename */
const char *ifname = NULL;
cmd.getParam(1, ifname);
+
/* check input file */
if ((ifname != NULL) && (strlen(ifname) > 0))
{
/* read DICOM file or data set */
DcmFileFormat dfile;
- OFCondition status = dfile.loadFile(ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);
+ status = dfile.loadFile(ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);
if (status.good())
{
DcmDataset *dset = dfile.getDataset();
- OFString csetString;
- if (dset->findAndGetOFStringArray(DCM_SpecificCharacterSet, csetString).good())
+ /* check for SpecificCharacterSet on any data set level */
+ if (dset->tagExistsWithValue(DCM_SpecificCharacterSet, OFTrue /*searchIntoSub*/))
{
- if (csetString.compare("ISO_IR 6") == 0)
+ /* convert entire DICOM file or data set to UTF-8 encoding */
+ status = dfile.convertToUTF8();
+ if (status.bad())
{
- /* SpecificCharacterSet indicates ASCII without extended characters.
- * If this is true, no conversion is necessary. Check for extended characters.
- */
- if (dset->containsExtendedCharacters(OFFalse /*checkAllStrings*/))
- {
- OFLOG_FATAL(dcm2jsonLogger, "dataset contains extended characters but SpecificCharacterSet (0008,0005) is 'ISO_IR 6'");
- result = EXITCODE_CANNOT_CONVERT_TO_UNICODE;
- }
- }
- else if (csetString.compare("ISO_IR 192") == 0)
- {
- /* DICOM dataset is already in UTF-8, no conversion necessary */
- }
- else
- {
- /* we have a character set other than ASCII or UTF-8. Perform conversion. */
-#ifdef DCMTK_ENABLE_CHARSET_CONVERSION
- /* convert all DICOM strings to UTF-8 */
- OFLOG_INFO(dcm2jsonLogger, "converting all element values that are affected by SpecificCharacterSet (0008,0005) to UTF-8");
- status = dset->convertToUTF8();
- if (status.bad())
- {
- OFLOG_FATAL(dcm2jsonLogger, status.text() << ": converting file to UTF-8: " << ifname);
- result = EXITCODE_CANNOT_CONVERT_TO_UNICODE;
- }
-#else
- OFLOG_FATAL(dcm2jsonLogger, "character set conversion not available");
+ OFLOG_FATAL(dcm2jsonLogger, status.text() << ": converting file to UTF-8: " << ifname);
result = EXITCODE_CANNOT_CONVERT_TO_UNICODE;
-#endif
}
}
else
{
- /* SpecificCharacterSet not present */
- if (dset->containsExtendedCharacters(OFFalse /*checkAllStrings*/))
- {
- OFLOG_FATAL(dcm2jsonLogger, "dataset contains extended characters but no SpecificCharacterSet (0008,0005)");
- result = EXITCODE_CANNOT_CONVERT_TO_UNICODE;
- }
+ if (dset->containsExtendedCharacters(OFFalse /*checkAllStrings*/))
+ {
+ OFLOG_ERROR(dcm2jsonLogger, OFFIS_CONSOLE_APPLICATION << ": SpecificCharacterSet (0008,0005) element "
+ << "absent (at all levels of the data set) but extended characters used in file: " << ifname);
+ result = EXITCODE_CANNOT_CONVERT_TO_UNICODE;
+ }
}
if (result == 0)
{
+
+ // look for the SOP instance UID, first in the dataset, then in the metaheader
+ OFString subDir;
+ OFString bulkDir = opt_bulk_dir;
+ OFString bulkURIPrefixWithSubdir;
+ if (opt_bulk_uri_prefix) bulkURIPrefixWithSubdir = opt_bulk_uri_prefix;
+ if ((opt_min_bulk_size >= 0) && opt_bulk_subdir)
+ {
+ if (dfile.getDataset()->findAndGetOFString(DCM_SOPInstanceUID, subDir).bad()
+ && dfile.getMetaInfo()->findAndGetOFString(DCM_SOPInstanceUID, subDir).bad())
+ {
+ // no SOP instance UID found. Use hard coded default UID instead.
+ subDir = DCM2JSON_WELL_KNOWN_UID;
+ }
+
+ bulkURIPrefixWithSubdir.append(subDir);
+ bulkURIPrefixWithSubdir.append("/");
+
+ bulkDir.append(1, PATH_SEPARATOR);
+ bulkDir.append(subDir);
+ if (! OFStandard::dirExists(bulkDir))
+ {
+ status = OFStandard::createDirectory(bulkDir, opt_bulk_dir);
+ if (status.bad())
+ {
+ OFLOG_FATAL(dcm2jsonLogger, status.text() << ": " << ifname);
+ return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+ }
+ }
+ }
+
/* if second parameter is present, it is treated as the output filename ("stdout" otherwise) */
if (cmd.getParamCount() == 2)
{
if (stream.good())
{
/* write content in JSON format to file */
- status = writeFile(stream, ifname, &dfile, opt_readMode, opt_format, opt_addMetaInformation, opt_encode_extended, opt_ns_policy);
+ status = writeFile(stream, &dfile, opt_readMode, opt_format, opt_addMetaInformation,
+ opt_encode_extended, opt_ns_policy, opt_min_bulk_size, bulkURIPrefixWithSubdir.c_str(), bulkDir.c_str());
if (status.bad())
{
OFLOG_FATAL(dcm2jsonLogger, status.text() << ": " << ifname);
else
{
/* write content in JSON format to standard output */
- status = writeFile(COUT, ifname, &dfile, opt_readMode, opt_format, opt_addMetaInformation, opt_encode_extended, opt_ns_policy);
+ status = writeFile(COUT, &dfile, opt_readMode, opt_format, opt_addMetaInformation,
+ opt_encode_extended, opt_ns_policy, opt_min_bulk_size, bulkURIPrefixWithSubdir.c_str(), bulkDir.c_str());
if (status.bad())
{
OFLOG_FATAL(dcm2jsonLogger, status.text() << ": " << ifname);
/*
*
- * Copyright (C) 2007-2024, OFFIS e.V.
+ * Copyright (C) 2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* Module: dcmdata
*
- * Author: Marco Eichelberg
+ * Authors: Marco Eichelberg
*
- * Purpose: Extract PDF file from DICOM encapsulated PDF storage object
+ * Purpose: Proxy stub that calls dcmdecap
*
*/
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/ofstub.h"
-BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h> /* for O_RDONLY */
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h> /* required for sys/stat.h */
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h> /* for stat, fstat */
-#endif
-END_EXTERN_C
-
-#include "dcmtk/dcmdata/dctk.h"
-#include "dcmtk/dcmdata/cmdlnarg.h"
-#include "dcmtk/ofstd/ofconapp.h"
-#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */
-#include "dcmtk/ofstd/ofstd.h"
-#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */
-
-#ifdef WITH_ZLIB
-#include <zlib.h> /* for zlibVersion() */
-#endif
-
-#define OFFIS_CONSOLE_APPLICATION "dcm2pdf"
-
-static OFLogger dcm2pdfLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
-
-static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
- OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
-
-#define FILENAME_PLACEHOLDER "#f"
-
-static OFString replaceChars(const OFString &srcstr, const OFString &pattern, const OFString &substitute)
-/*
- * This function replaces all occurrences of pattern in srcstr with substitute and returns
- * the result as a new OFString variable. Note that srcstr itself will not be changed.
- *
- * Parameters:
- * srcstr - [in] The source string.
- * pattern - [in] The pattern string which shall be substituted.
- * substitute - [in] The substitute for pattern in srcstr.
- */
-{
- OFString result = srcstr;
- size_t pos = 0;
-
- while (pos != OFString_npos)
- {
- pos = result.find(pattern, pos);
-
- if (pos != OFString_npos)
- {
- result.replace(pos, pattern.size(), substitute);
- pos += substitute.size();
- }
- }
-
- return result;
-}
-
-
-#define SHORTCOL 3
-#define LONGCOL 20
-
-int main(int argc, char *argv[])
+int main(int argc, char** argv)
{
- const char *opt_ifname = NULL;
- const char *opt_ofname = NULL;
- const char *opt_execString = NULL;
- E_FileReadMode opt_readMode = ERM_autoDetect;
- E_TransferSyntax opt_ixfer = EXS_Unknown;
-
- OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Extract PDF file from DICOM encapsulated PDF", rcsid);
- OFCommandLine cmd;
- cmd.setOptionColumns(LONGCOL, SHORTCOL);
- cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
-
- cmd.addParam("dcmfile-in", "DICOM input filename (\"-\" for stdin)");
- cmd.addParam("pdffile-out", "PDF output filename");
-
- cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2);
- cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive);
- cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive);
- OFLog::addOptions(cmd);
-
- cmd.addGroup("input options:");
- cmd.addSubGroup("input file format:");
- cmd.addOption("--read-file", "+f", "read file format or data set (default)");
- cmd.addOption("--read-file-only", "+fo", "read file format only");
- cmd.addOption("--read-dataset", "-f", "read data set without file meta information");
- cmd.addSubGroup("input transfer syntax:");
- cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)");
- cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header");
- cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS");
- cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS");
- cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS");
- cmd.addSubGroup("parsing of odd-length attributes:");
- cmd.addOption("--accept-odd-length", "+ao", "accept odd length attributes (default)");
- cmd.addOption("--assume-even-length", "+ae", "assume real length is one byte larger");
- cmd.addSubGroup("handling of undefined length UN elements:");
- cmd.addOption("--enable-cp246", "+ui", "read undefined len UN as implicit VR (default)");
- cmd.addOption("--disable-cp246", "-ui", "read undefined len UN as explicit VR");
- cmd.addSubGroup("handling of defined length UN elements:");
- cmd.addOption("--retain-un", "-uc", "retain elements as UN (default)");
- cmd.addOption("--convert-un", "+uc", "convert to real VR if known");
- cmd.addSubGroup("automatic data correction:");
- cmd.addOption("--enable-correction", "+dc", "enable automatic data correction (default)");
- cmd.addOption("--disable-correction", "-dc", "disable automatic data correction");
-#ifdef WITH_ZLIB
- cmd.addSubGroup("bitstream format of deflated input:");
- cmd.addOption("--bitstream-deflated", "+bd", "expect deflated bitstream (default)");
- cmd.addOption("--bitstream-zlib", "+bz", "expect deflated zlib bitstream");
-#endif
-
- cmd.addGroup("processing options:");
- cmd.addSubGroup("execution options:");
- cmd.addOption("--exec", "-x", 1, "[c]ommand: string",
- "execute command c after PDF extraction");
- /* evaluate command line */
- prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
- if (app.parseCommandLine(cmd, argc, argv))
- {
- /* check exclusive options first */
- if (cmd.hasExclusiveOption())
- {
- if (cmd.findOption("--version"))
- {
- app.printHeader(OFTrue /*print host identifier*/);
- COUT << OFendl << "External libraries used:";
-#ifdef WITH_ZLIB
- COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
-#else
- COUT << " none" << OFendl;
-#endif
- return EXITCODE_NO_ERROR;
- }
- }
-
- /* command line parameters and options */
- cmd.getParam(1, opt_ifname);
- cmd.getParam(2, opt_ofname);
-
- OFLog::configureFromCommandLine(cmd, app);
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--read-file")) opt_readMode = ERM_autoDetect;
- if (cmd.findOption("--read-file-only")) opt_readMode = ERM_fileOnly;
- if (cmd.findOption("--read-dataset")) opt_readMode = ERM_dataset;
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--read-xfer-auto"))
- opt_ixfer = EXS_Unknown;
- if (cmd.findOption("--read-xfer-detect"))
- dcmAutoDetectDatasetXfer.set(OFTrue);
- if (cmd.findOption("--read-xfer-little"))
- {
- app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset);
- opt_ixfer = EXS_LittleEndianExplicit;
- }
- if (cmd.findOption("--read-xfer-big"))
- {
- app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset);
- opt_ixfer = EXS_BigEndianExplicit;
- }
- if (cmd.findOption("--read-xfer-implicit"))
- {
- app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset);
- opt_ixfer = EXS_LittleEndianImplicit;
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--accept-odd-length"))
- {
- dcmAcceptOddAttributeLength.set(OFTrue);
- }
- if (cmd.findOption("--assume-even-length"))
- {
- dcmAcceptOddAttributeLength.set(OFFalse);
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--enable-cp246"))
- {
- dcmEnableCP246Support.set(OFTrue);
- }
- if (cmd.findOption("--disable-cp246"))
- {
- dcmEnableCP246Support.set(OFFalse);
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--retain-un"))
- {
- dcmEnableUnknownVRConversion.set(OFFalse);
- }
- if (cmd.findOption("--convert-un"))
- {
- dcmEnableUnknownVRConversion.set(OFTrue);
- }
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--enable-correction"))
- {
- dcmEnableAutomaticInputDataCorrection.set(OFTrue);
- }
- if (cmd.findOption("--disable-correction"))
- {
- dcmEnableAutomaticInputDataCorrection.set(OFFalse);
- }
- cmd.endOptionBlock();
-
-#ifdef WITH_ZLIB
- cmd.beginOptionBlock();
- if (cmd.findOption("--bitstream-deflated"))
- {
- dcmZlibExpectRFC1950Encoding.set(OFFalse);
- }
- if (cmd.findOption("--bitstream-zlib"))
- {
- dcmZlibExpectRFC1950Encoding.set(OFTrue);
- }
- cmd.endOptionBlock();
-#endif
-
- if (cmd.findOption("--exec"))
- app.checkValue(cmd.getValue(opt_execString));
- }
-
- /* print resource identifier */
- OFLOG_DEBUG(dcm2pdfLogger, rcsid << OFendl);
-
- /* make sure data dictionary is loaded */
- if (!dcmDataDict.isDictionaryLoaded())
- {
- OFLOG_WARN(dcm2pdfLogger, "no data dictionary loaded, check environment variable: "
- << DCM_DICT_ENVIRONMENT_VARIABLE);
- }
-
- // open inputfile
- if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0))
- {
- OFLOG_FATAL(dcm2pdfLogger, "invalid filename: <empty string>");
- return EXITCODE_NO_INPUT_FILES;
- }
-
- DcmFileFormat fileformat;
- DcmDataset * dataset = fileformat.getDataset();
-
- OFLOG_INFO(dcm2pdfLogger, "open input file " << opt_ifname);
-
- OFCondition error = fileformat.loadFile(opt_ifname, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);
-
- if (error.bad())
- {
- OFLOG_FATAL(dcm2pdfLogger, error.text() << ": reading file: " << opt_ifname);
- return EXITCODE_CANNOT_READ_INPUT_FILE;
- }
-
- OFString sopClass;
- error = dataset->findAndGetOFString(DCM_SOPClassUID, sopClass);
- if (error.bad() || sopClass != UID_EncapsulatedPDFStorage)
- {
- OFLOG_FATAL(dcm2pdfLogger, "not an Encapsulated PDF object: " << opt_ifname);
- return EXITCODE_INVALID_INPUT_FILE;
- }
-
- DcmElement *delem = NULL;
- error = dataset->findAndGetElement(DCM_EncapsulatedDocument, delem);
- if (error.bad() || delem == NULL)
- {
- OFLOG_FATAL(dcm2pdfLogger, "Encapsulated Document missing.");
- return EXITCODE_INVALID_INPUT_FILE;
- }
-
- Uint32 len = delem->getLength();
- Uint8 *pdfDocument = NULL;
- error = delem->getUint8Array(pdfDocument);
- if (error.bad() || pdfDocument == NULL || len == 0)
- {
- OFLOG_FATAL(dcm2pdfLogger, "Encapsulated Document empty or wrong VR.");
- return EXITCODE_INVALID_INPUT_FILE;
- }
-
- /* strip pad byte at end of file, if there is one. The PDF format expects
- * files to end with %%EOF followed by CR/LF (although in some cases the
- * CR/LF may be missing or you might only find CR or LF).
- * If the last character of the file is not a CR or LF, and not the
- * letter 'F', we assume it is either trailing garbage or a pad byte, and remove it.
- */
- if (pdfDocument[len-1] != 10 && pdfDocument[len-1] != 13 && pdfDocument[len-1] != 'F')
- {
- --len;
- }
-
- OFLOG_INFO(dcm2pdfLogger, "writing PDF file to " << opt_ofname);
- FILE *pdffile = fopen(opt_ofname, "wb");
- if (pdffile == NULL)
- {
- OFLOG_FATAL(dcm2pdfLogger, "unable to create file " << opt_ofname);
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- if (len != fwrite(pdfDocument, 1, len, pdffile))
- {
- OFLOG_FATAL(dcm2pdfLogger, "write error in file " << opt_ofname);
- fclose(pdffile);
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- if(fclose(pdffile))
- {
- OFLOG_FATAL(dcm2pdfLogger, "write error in file " << opt_ofname);
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- OFLOG_INFO(dcm2pdfLogger, "conversion successful");
-
- if (opt_execString)
- {
- OFString cmdStr = opt_execString;
- cmdStr = replaceChars(cmdStr, OFString(FILENAME_PLACEHOLDER), opt_ofname);
-
- // Execute command and return result
- return system(cmdStr.c_str());
- }
-
- return EXITCODE_NO_ERROR;
+ // call stub. Will not return on Posix systems.
+ return OFstub_main(argc, argv, "dcm2pdf", "dcmdecap");
}
/*
*
- * Copyright (C) 2002-2022, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/* SpecificCharacterSet is not present in the dataset */
if (dset->containsExtendedCharacters(checkAllStrings))
{
+ OFString sopClass;
+ /* check whether this file is a DICOMDIR */
+ const OFBool isDICOMDIR = dfile.getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).good() &&
+ (sopClass == UID_MediaStorageDirectoryStorage);
if (defaultCharset == NULL)
{
- /* the dataset contains non-ASCII characters that really should not be there */
- OFLOG_ERROR(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": SpecificCharacterSet (0008,0005) "
- << "element absent (on the main data set level) but extended characters used in file: " << ifname);
- OFLOG_DEBUG(dcm2xmlLogger, "use option --charset-assume to manually specify an appropriate character set");
- result = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, "Missing Specific Character Set");;
+ if (isDICOMDIR)
+ {
+ /* check for SpecificCharacterSet on any data set level */
+ if (dset->tagExistsWithValue(DCM_SpecificCharacterSet, OFTrue /*searchIntoSub*/))
+ {
+ /* for now, we assume that everything is ok */
+ result = EC_Normal;
+ } else {
+ OFLOG_ERROR(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": SpecificCharacterSet (0008,0005) element "
+ << "absent (at all levels of the data set) but extended characters used in file: " << ifname);
+ OFLOG_DEBUG(dcm2xmlLogger, "try using option --charset-assume to manually specify an appropriate character set");
+ result = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, "Missing Specific Character Set");
+ }
+ } else {
+ /* the dataset contains non-ASCII characters that really should not be there */
+ OFLOG_ERROR(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": SpecificCharacterSet (0008,0005) element "
+ << "absent (at the main level of the data set) but extended characters used in file: " << ifname);
+ OFLOG_DEBUG(dcm2xmlLogger, "use option --charset-assume to manually specify an appropriate character set");
+ result = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, "Missing Specific Character Set");
+ }
} else {
result = EC_Normal;
csetString = defaultCharset;
<< defaultCharset << "' specified with option --charset-assume not supported");
result = makeOFCondition(OFM_dcmdata, EC_CODE_CannotSelectCharacterSet, OF_error, "Cannot select character set");
}
- if (result.good())
+ if (result.good() && !isDICOMDIR)
{
- OFString sopClass;
- /* check whether this file is a DICOMDIR */
- if (dfile.getMetaInfo()->findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClass).bad() ||
- (sopClass != UID_MediaStorageDirectoryStorage))
- {
- OFLOG_INFO(dcm2xmlLogger, "inserting SpecificCharacterSet (0008,0005) element with value '" << csetString << "'");
- /* insert the SpecificCharacterSet (0008,0005) element with new value */
- result = dset->putAndInsertOFStringArray(DCM_SpecificCharacterSet, csetString);
- }
+ OFLOG_INFO(dcm2xmlLogger, "inserting SpecificCharacterSet (0008,0005) element with value '" << csetString << "'");
+ /* insert the SpecificCharacterSet (0008,0005) element with new value */
+ result = dset->putAndInsertOFStringArray(DCM_SpecificCharacterSet, csetString);
}
}
} else {
OFCondition result = EC_IllegalParameter;
if (ifname != NULL)
{
- DcmDataset *dset = dfile.getDataset();
/* convert all DICOM strings to UTF-8 (if requested) */
if (convertToUTF8)
{
OFLOG_INFO(dcm2xmlLogger, "converting all element values that are affected by SpecificCharacterSet (0008,0005) to UTF-8");
/* expect that SpecificCharacterSet contains the correct value (defined term) */
- result = dset->convertToUTF8();
+ result = dfile.convertToUTF8();
if (result.good())
{
/* if conversion was successful, set XML character encoding accordingly */
(sopClass == UID_MediaStorageDirectoryStorage))
{
/* ... with one or more SpecificCharacterSet elements */
- if (dset->tagExistsWithValue(DCM_SpecificCharacterSet, OFTrue /*searchIntoSub*/))
+ if (dfile.getDataset()->tagExistsWithValue(DCM_SpecificCharacterSet, OFTrue /*searchIntoSub*/))
{
OFLOG_WARN(dcm2xmlLogger, OFFIS_CONSOLE_APPLICATION << ": this is a DICOMDIR file, which can contain more than one "
<< "SpecificCharacterSet (0008,0005) element ... using option --convert-to-utf8 is strongly recommended");
--- /dev/null
+/*
+ *
+ * Copyright (C) 2007-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Marco Eichelberg, Tingyan Xu
+ *
+ * Purpose: Extract encapsulated file from DICOM encapsulated storage object
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/dcmdata/cmdlnarg.h"
+#include "dcmtk/ofstd/ofconapp.h"
+#include "dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */
+#include "dcmtk/dcmdata/dcistrmz.h" /* for dcmZlibExpectRFC1950Encoding */
+#include "dcmtk/dcmdata/dcdocdec.h" /* for class DcmDocumentDecapsulator */
+#include "dcmtk/dcmdata/dcdict.h" /* for data dictionary */
+
+#ifdef WITH_ZLIB
+#include <zlib.h> /* for zlibVersion() */
+#endif
+
+#define OFFIS_CONSOLE_APPLICATION "dcmdecap"
+
+static OFLogger dcmdecapLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
+static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v" OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
+
+#define SHORTCOL 3
+#define LONGCOL 20
+#define EXITCODE_EXEC_FAILED 91
+
+
+static void addInputOptions(OFCommandLine& cmd)
+{
+ cmd.addGroup("input options:");
+ cmd.addSubGroup("input file format:");
+ cmd.addOption("--read-file", "+f", "read file format or data set (default)");
+ cmd.addOption("--read-file-only", "+fo", "read file format only");
+ cmd.addOption("--read-dataset", "-f", "read data set without file meta information");
+
+ cmd.addSubGroup("input transfer syntax:");
+ cmd.addOption("--read-xfer-auto", "-t=", "use TS recognition (default)");
+ cmd.addOption("--read-xfer-detect", "-td", "ignore TS specified in the file meta header");
+ cmd.addOption("--read-xfer-little", "-te", "read with explicit VR little endian TS");
+ cmd.addOption("--read-xfer-big", "-tb", "read with explicit VR big endian TS");
+ cmd.addOption("--read-xfer-implicit", "-ti", "read with implicit VR little endian TS");
+
+ cmd.addSubGroup("parsing of odd-length attributes:");
+ cmd.addOption("--accept-odd-length", "+ao", "accept odd length attributes (default)");
+ cmd.addOption("--assume-even-length", "+ae", "assume real length is one byte larger");
+
+ cmd.addSubGroup("handling of undefined length UN elements:");
+ cmd.addOption("--enable-cp246", "+ui", "read undefined len UN as implicit VR (default)");
+ cmd.addOption("--disable-cp246", "-ui", "read undefined len UN as explicit VR");
+
+ cmd.addSubGroup("handling of defined length UN elements:");
+ cmd.addOption("--retain-un", "-uc", "retain elements as UN (default)");
+ cmd.addOption("--convert-un", "+uc", "convert to real VR if known");
+
+ cmd.addSubGroup("automatic data correction:");
+ cmd.addOption("--enable-correction", "+dc", "enable automatic data correction (default)");
+ cmd.addOption("--disable-correction", "-dc", "disable automatic data correction");
+
+#ifdef WITH_ZLIB
+ cmd.addSubGroup("bitstream format of deflated input:");
+ cmd.addOption("--bitstream-deflated", "+bd", "expect deflated bitstream (default)");
+ cmd.addOption("--bitstream-zlib", "+bz", "expect deflated zlib bitstream");
+#endif
+}
+
+static void parseInputOptions(OFConsoleApplication& app, OFCommandLine& cmd, DcmDocumentDecapsulator& docdec)
+{
+ E_FileReadMode opt_readMode = ERM_autoDetect;
+ E_TransferSyntax opt_ixfer = EXS_Unknown;
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--read-file"))
+ {
+ opt_readMode = ERM_autoDetect;
+ docdec.setReadMode(opt_readMode);
+ }
+ if (cmd.findOption("--read-file-only"))
+ {
+ opt_readMode = ERM_fileOnly;
+ docdec.setReadMode(opt_readMode);
+ }
+ if (cmd.findOption("--read-dataset"))
+ {
+ opt_readMode = ERM_dataset;
+ docdec.setReadMode(opt_readMode);
+ }
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--read-xfer-auto"))
+ {
+ opt_ixfer = EXS_Unknown;
+ docdec.setInputXferSyntax(opt_ixfer);
+ }
+ if (cmd.findOption("--read-xfer-detect"))
+ {
+ dcmAutoDetectDatasetXfer.set(OFTrue);
+ }
+ if (cmd.findOption("--read-xfer-little"))
+ {
+ opt_ixfer = EXS_LittleEndianExplicit;
+ app.checkDependence("--read-xfer-little", "--read-dataset", opt_readMode == ERM_dataset);
+ docdec.setInputXferSyntax(opt_ixfer);
+ }
+ if (cmd.findOption("--read-xfer-big"))
+ {
+ opt_ixfer = EXS_BigEndianExplicit;
+ app.checkDependence("--read-xfer-big", "--read-dataset", opt_readMode == ERM_dataset);
+ docdec.setInputXferSyntax(opt_ixfer);
+ }
+ if (cmd.findOption("--read-xfer-implicit"))
+ {
+ opt_ixfer = EXS_LittleEndianImplicit;
+ app.checkDependence("--read-xfer-implicit", "--read-dataset", opt_readMode == ERM_dataset);
+ docdec.setInputXferSyntax(opt_ixfer);
+ }
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--accept-odd-length"))
+ {
+ dcmAcceptOddAttributeLength.set(OFTrue);
+ }
+ if (cmd.findOption("--assume-even-length"))
+ {
+ dcmAcceptOddAttributeLength.set(OFFalse);
+ }
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--enable-cp246"))
+ {
+ dcmEnableCP246Support.set(OFTrue);
+ }
+ if (cmd.findOption("--disable-cp246"))
+ {
+ dcmEnableCP246Support.set(OFFalse);
+ }
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--retain-un"))
+ {
+ dcmEnableUnknownVRConversion.set(OFFalse);
+ }
+ if (cmd.findOption("--convert-un"))
+ {
+ dcmEnableUnknownVRConversion.set(OFTrue);
+ }
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--enable-correction"))
+ {
+ dcmEnableAutomaticInputDataCorrection.set(OFTrue);
+ }
+ if (cmd.findOption("--disable-correction"))
+ {
+ dcmEnableAutomaticInputDataCorrection.set(OFFalse);
+ }
+ cmd.endOptionBlock();
+
+#ifdef WITH_ZLIB
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--bitstream-deflated"))
+ {
+ dcmZlibExpectRFC1950Encoding.set(OFFalse);
+ }
+ if (cmd.findOption("--bitstream-zlib"))
+ {
+ dcmZlibExpectRFC1950Encoding.set(OFTrue);
+ }
+ cmd.endOptionBlock();
+#endif
+}
+
+static void addProcessingOptions(OFCommandLine& cmd)
+{
+ cmd.addGroup("processing options:");
+ cmd.addSubGroup("execution options:");
+ cmd.addOption("--exec", "-x", 1, "[c]ommand: string",
+ "execute command c after document extraction");
+}
+
+static void parseProcessingOptions(OFConsoleApplication& app, OFCommandLine& cmd, DcmDocumentDecapsulator& docdec)
+{
+ const char *c;
+ if (cmd.findOption("--exec"))
+ {
+ app.checkValue(cmd.getValue(c));
+ docdec.setExecString(c);
+ }
+}
+
+static void addCommandLineOptions(OFCommandLine& cmd)
+{
+ cmd.setOptionColumns(LONGCOL, SHORTCOL);
+ cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
+ cmd.addParam("dcmfile-in", "DICOM input filename (\"-\" for stdin)");
+ cmd.addParam("encfile-out", "Encapsulated document output filename\n(\"-\" for stdout)");
+ cmd.addGeneralOptions(LONGCOL, SHORTCOL);
+
+ OFLog::addOptions(cmd);
+
+ addInputOptions(cmd);
+ addProcessingOptions(cmd);
+}
+
+static void parseCommandLineOptions(OFConsoleApplication& app, OFCommandLine& cmd, DcmDocumentDecapsulator& docdec)
+{
+ const char *c;
+ cmd.getParam(1, c);
+ docdec.setInputFile(c);
+ cmd.getParam(2, c);
+ docdec.setOutputFile(c);
+ OFLog::configureFromCommandLine(cmd, app);
+ parseInputOptions(app, cmd, docdec);
+ parseProcessingOptions(app, cmd, docdec);
+}
+
+
+int main(int argc, char* argv[])
+{
+ DcmDocumentDecapsulator docdec;
+ OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Extract file from DICOM encapsulated storage", rcsid);
+ OFCommandLine cmd;
+ addCommandLineOptions(cmd);
+
+ // evaluate command line
+ prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
+ if (app.parseCommandLine(cmd, argc, argv))
+ {
+ // check exclusive options first
+ if (cmd.hasExclusiveOption())
+ {
+ if (cmd.findOption("--version"))
+ {
+ app.printHeader(OFTrue /*print host identifier*/);
+ COUT << OFendl << "External libraries used:";
+#ifdef WITH_ZLIB
+ COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
+#else
+ COUT << " none" << OFendl;
+#endif
+ return EXITCODE_NO_ERROR;
+ }
+ }
+
+ // parse command line parameters and options
+ parseCommandLineOptions(app, cmd, docdec);
+ }
+
+ // print resource identifier
+ OFLOG_DEBUG(dcmdecapLogger, rcsid << OFendl);
+
+ // make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFLOG_WARN(dcmdecapLogger, "no data dictionary loaded, check environment variable: "
+ << DCM_DICT_ENVIRONMENT_VARIABLE);
+ }
+
+ // read the DICOM file
+ OFCondition cond = docdec.loadDICOMFile();
+ if (cond == EC_InvalidFilename) return EXITCODE_NO_INPUT_FILES;
+ else if (cond.bad()) return EXITCODE_CANNOT_READ_INPUT_FILE;
+
+ // extract the encapsulated document and write to file
+ cond = docdec.writeEncapsulatedContentToFile();
+ if (cond == EC_MissingAttribute) return EXITCODE_INVALID_INPUT_FILE;
+ else if (cond.bad()) return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+
+ // execute the command line (if defined)
+ cond = docdec.executeCommand();
+ if (cond.bad()) return EXITCODE_EXEC_FAILED;
+
+ // all done
+ return EXITCODE_NO_ERROR;
+}
--- /dev/null
+/*
+ *
+ * Copyright (C) 2018-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Pedro Arizpe, Marco Eichelberg
+ *
+ * Purpose: Encapsulate document into DICOM format
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first*/
+#include "dcmtk/dcmdata/dcencdoc.h"
+#include "dcmtk/dcmdata/cmdlnarg.h"
+#include "dcmtk/dcmdata/dcuid.h"
+#include "dcmtk/dcmdata/dcdict.h"
+#include "dcmtk/ofstd/ofconapp.h"
+
+
+#ifdef WITH_ZLIB
+#include <zlib.h> /* for zlibVersion() */
+#endif
+
+#define OFFIS_CONSOLE_APPLICATION "dcmencap"
+
+static OFLogger dcmencapLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
+
+static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
+OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
+
+int main(int argc, char *argv[])
+{
+ OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encapsulate document into DICOM format", rcsid);
+ OFCommandLine cmd;
+ OFCondition result = EC_Normal;
+ dcmEnableGenerationOfNewVRs();
+
+ // process command line options
+ DcmEncapsulatedDocument encapsulator;
+ encapsulator.addCommandlineOptions(cmd);
+ prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
+
+ if (app.parseCommandLine(cmd, argc, argv))
+ {
+ OFLOG_TRACE (dcmencapLogger, "Checking exclusive options first");
+ if (cmd.hasExclusiveOption())
+ {
+ if (cmd.findOption("--version"))
+ {
+ app.printHeader(OFTrue /*print host identifier*/);
+ COUT << OFendl << "External libraries used: ";
+#ifdef WITH_ZLIB
+ COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
+#else
+ COUT << " none" << OFendl;
+#endif
+ return EXITCODE_NO_ERROR;
+ }
+ }
+ encapsulator.parseArguments(app, cmd);
+ }
+
+ //print resource identifier
+ OFLOG_DEBUG(dcmencapLogger, rcsid << OFendl);
+
+ OFLOG_DEBUG(dcmencapLogger, "making sure data dictionary is loaded");
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFLOG_WARN(dcmencapLogger, "no data dictionary loaded, check environment variable: "
+ << DCM_DICT_ENVIRONMENT_VARIABLE);
+ }
+
+ // read input document and place it into the dataset.
+ // This call will also determine the file type (unless set by command line option).
+ OFLOG_INFO(dcmencapLogger, "reading file '" << encapsulator.getInputFileName() << "'");
+ result = encapsulator.insertEncapsulatedDocument();
+ if (result.bad()) return EXITCODE_INVALID_INPUT_FILE;
+
+ // read series file (if any) and otherwise generate study and series UID
+ result = encapsulator.createIdentifiers();
+ if (result.bad()) return EXITCODE_INVALID_INPUT_FILE;
+
+ // perform document format specific processing (such as reading information from the CDA content)
+ result = encapsulator.formatSpecificProcessing();
+ if (result.bad()) return EXITCODE_INVALID_INPUT_FILE;
+
+ // write DICOM header attributes to dataset
+ result = encapsulator.createHeader();
+ if (result.bad()) return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+
+ // apply command line override keys (if any)
+ result = encapsulator.applyOverrideKeys();
+ if (result.bad()) return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+
+ OFLOG_INFO(dcmencapLogger, "writing encapsulated DICOM object as file '" << encapsulator.getOutputFileName() << "'");
+
+ // write DICOM file
+ result = encapsulator.saveFile();
+ if (result.bad()) return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+
+ OFLOG_INFO(dcmencapLogger, "DICOM encapsulation successful");
+ return EXITCODE_NO_ERROR;
+}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// if defined, use createValueFromTempFile() for large binary data files
//#define EXPERIMENTAL_READ_FROM_FILE
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/ofstd/ofconapp.h"
#include "dcmtk/ofstd/ofstream.h"
/*
*
- * Copyright (C) 2007-2023, OFFIS e.V.
+ * Copyright (C) 2007-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
cond = i2d.convertNextFrame(inputPlug, ++frameNum);
}
+ // adjust byte order of pixel data to local OW byte order
+ if (cond.good()) cond = i2d.adjustByteOrder(inputFiles.size());
+
// update offset table if image type is encapsulated
if (cond.good()) cond = i2d.updateOffsetTable();
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Tingyan Xu
+ *
+ * Purpose: Convert JSON DICOM document to binary DICOM file
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/ofconapp.h"
+#include "dcmtk/dcmdata/cmdlnarg.h"
+#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */
+#include "dcmtk/dcmdata/dcfilefo.h" /* for class DcmFileFormat */
+#include "dcmtk/dcmdata/dcdeftag.h" /* for tag keys */
+#include "dcmtk/dcmdata/dcuid.h" /* for UID constants */
+#include "dcmtk/dcmdata/dcdict.h" /* for the data dictionary */
+#include "dcmtk/dcmdata/dcjsonrd.h" /* for class DcmJSONReader */
+
+#ifdef WITH_ZLIB
+#include <zlib.h> /* for zlibVersion() */
+#endif
+
+#define OFFIS_CONSOLE_APPLICATION "json2dcm"
+#define OFFIS_CONSOLE_DESCRIPTION "Convert JSON document to DICOM file or data set"
+
+/* Error codes */
+
+#define EXITCODE_INVALID_JSON_CONTENT 65
+#define EXITCODE_BULKDATA_URI_NOT_SUPPORTED 66
+
+static OFLogger json2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
+
+static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
+OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
+
+void addInputOptions(OFCommandLine& cmd)
+{
+ cmd.addGroup("input options:");
+ cmd.addSubGroup("input file format:");
+ cmd.addOption("--read-meta-info", "+f", "read meta information if present (default)");
+ cmd.addOption("--ignore-meta-info", "-f", "ignore file meta information");
+}
+
+void addProcessOptions(OFCommandLine& cmd)
+{
+ cmd.addGroup("processing options:");
+ cmd.addSubGroup("unique identifiers:");
+ cmd.addOption("--generate-new-uids", "+Ug", "generate new Study/Series/SOP Instance UID");
+ cmd.addOption("--dont-overwrite-uids", "-Uo", "do not overwrite existing UIDs (default)");
+ cmd.addOption("--overwrite-uids", "+Uo", "overwrite existing UIDs");
+ cmd.addSubGroup("bulkdata URI handling:");
+ cmd.addOption("--parse-bulkdata-uri", "+Bu", "parse Bulkdata URIs (default)");
+ cmd.addOption("--ignore-bulkdata-uri", "-Bu", "ignore Bulkdata URIs");
+ cmd.addOption("--add-bulkdata-dir", "+Bd", 1, "[d]irectory: string",
+ "add d to list of permitted bulk data sources");
+ cmd.addSubGroup("handling of arrays with multiple data sets:");
+ cmd.addOption("--array-reject", "-ar", "reject multiple data sets (default)");
+ cmd.addOption("--array-select", "+as", 1, "[n]umber: integer",
+ "select data set n from array");
+ cmd.addOption("--array-sequence", "+ar", "store all data sets in private sequence");
+}
+
+void addOutputOptions(OFCommandLine& cmd)
+{
+ cmd.addGroup("output options:");
+ cmd.addSubGroup("output file format:");
+ cmd.addOption("--write-file", "+F", "write file format (default)");
+ cmd.addOption("--write-dataset", "-F", "write data set without file meta information");
+ cmd.addOption("--update-meta-info", "+Fu", "update particular file meta information");
+ cmd.addSubGroup("output transfer syntax:");
+ cmd.addOption("--write-xfer-same", "+t=", "write with same TS as input (default)");
+ cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian TS");
+ cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS");
+ cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS");
+#ifdef WITH_ZLIB
+ cmd.addOption("--write-xfer-deflated", "+td", "write with deflated expl. VR little endian TS");
+#endif
+ cmd.addSubGroup("error handling:");
+ cmd.addOption("--stop-on-error", "-E", "do not write if document is invalid (default)");
+ cmd.addOption("--ignore-errors", "+E", "attempt to write even if document is invalid");
+ cmd.addSubGroup("post-1993 value representations:");
+ cmd.addOption("--enable-new-vr", "+u", "enable support for new VRs (UN/UT) (default)");
+ cmd.addOption("--disable-new-vr", "-u", "disable support for new VRs, convert to OB");
+ cmd.addSubGroup("length encoding in sequences and items:");
+ cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)");
+ cmd.addOption("--length-undefined", "-e", "write with undefined lengths");
+ cmd.addSubGroup("charset handling:");
+ cmd.addOption("--charset-accept", "+c", "write with the given charset in JSON (default)");
+ cmd.addOption("--charset-replace", "-c", "replace the given charset in JSON with UTF-8");
+#ifdef WITH_ZLIB
+ cmd.addSubGroup("deflate compression level (only with --write-xfer-deflated):");
+ cmd.addOption("--compression-level", "+cl", 1, "[l]evel: integer (default: 6)",
+ "0=uncompressed, 1=fastest, 9=best compression");
+#endif
+}
+
+#define SHORTCOL 3
+#define LONGCOL 21
+
+void addJSON2DCMCommandlineOptions(OFCommandLine& cmd)
+{
+ cmd.setOptionColumns(LONGCOL, SHORTCOL);
+ cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
+
+ cmd.addParam("jsonfile-in", "JSON input filename to be converted\n(\"-\" for stdin)");
+ cmd.addParam("dcmfile-out", "DICOM output filename\n(\"-\" for stdout)");
+
+ cmd.addGeneralOptions(LONGCOL, SHORTCOL);
+ OFLog::addOptions(cmd);
+ addInputOptions(cmd);
+ addProcessOptions(cmd);
+ addOutputOptions(cmd);
+}
+
+/**
+ * function for parsing commandline arguments
+ */
+OFCondition parseArguments(
+ OFConsoleApplication& app,
+ OFCommandLine& cmd,
+ OFBool& opt_generateUIDs,
+ OFBool& opt_overwriteUIDs,
+ E_TransferSyntax& opt_xfer,
+ E_EncodingType& opt_enctype,
+ OFBool& opt_replaceCharset,
+ E_FileWriteMode& opt_writeMode,
+ const char*& opt_ifname,
+ const char*& opt_ofname,
+ DcmJSONReader& jsonReader
+)
+{
+ cmd.getParam(1, opt_ifname);
+ cmd.getParam(2, opt_ofname);
+
+ OFLog::configureFromCommandLine(cmd, app);
+
+ /* input options */
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--read-meta-info"))
+ jsonReader.setIgnoreMetaInfoPolicy(OFFalse);
+ if (cmd.findOption("--ignore-meta-info"))
+ jsonReader.setIgnoreMetaInfoPolicy(OFTrue);
+ cmd.endOptionBlock();
+
+ /* processing options */
+ if (cmd.findOption("--generate-new-uids"))
+ opt_generateUIDs = OFTrue;
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--dont-overwrite-uids"))
+ {
+ app.checkDependence("--dont-overwrite-uids", "--generate-new-uids", opt_generateUIDs);
+ opt_overwriteUIDs = OFFalse;
+ }
+ if (cmd.findOption("--overwrite-uids"))
+ {
+ app.checkDependence("--overwrite-uids", "--generate-new-uids", opt_generateUIDs);
+ opt_overwriteUIDs = OFTrue;
+ }
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--ignore-bulkdata-uri"))
+ {
+ jsonReader.setIgnoreBulkdataURIPolicy(OFTrue);
+ }
+ if (cmd.findOption("--parse-bulkdata-uri"))
+ {
+ jsonReader.setIgnoreBulkdataURIPolicy(OFFalse);
+ }
+ cmd.endOptionBlock();
+
+ if (cmd.findOption("--add-bulkdata-dir", 0, OFCommandLine::FOM_First))
+ {
+ OFCondition result;
+ const char *current = NULL;
+ do
+ {
+ app.checkValue(cmd.getValue(current));
+ result = jsonReader.addPermittedBulkdataPath(current);
+ if (result.bad()) return result;
+ } while (cmd.findOption("--add-bulkdata-dir", 0, OFCommandLine::FOM_Next));
+ }
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--array-reject"))
+ {
+ jsonReader.setArrayHandlingPolicy(-1);
+ }
+ if (cmd.findOption("--array-sequence"))
+ {
+ jsonReader.setArrayHandlingPolicy(0);
+ }
+ if (cmd.findOption("--array-select"))
+ {
+ OFCmdSignedInt arrayHandling = -1;
+ cmd.getValueAndCheckMin(arrayHandling, 1);
+ jsonReader.setArrayHandlingPolicy(arrayHandling);
+ }
+ cmd.endOptionBlock();
+
+ /* output options */
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--write-file"))
+ opt_writeMode = EWM_fileformat;
+ if (cmd.findOption("--write-dataset"))
+ opt_writeMode = EWM_dataset;
+ cmd.endOptionBlock();
+
+ if (cmd.findOption("--update-meta-info"))
+ {
+ app.checkConflict("--update-meta-info", "--write-dataset", opt_writeMode == EWM_dataset);
+ opt_writeMode = EWM_updateMeta;
+ }
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--write-xfer-same"))
+ opt_xfer = EXS_Unknown;
+ if (cmd.findOption("--write-xfer-little"))
+ opt_xfer = EXS_LittleEndianExplicit;
+ if (cmd.findOption("--write-xfer-big"))
+ opt_xfer = EXS_BigEndianExplicit;
+ if (cmd.findOption("--write-xfer-implicit"))
+ opt_xfer = EXS_LittleEndianImplicit;
+#ifdef WITH_ZLIB
+ if (cmd.findOption("--write-xfer-deflated"))
+ opt_xfer = EXS_DeflatedLittleEndianExplicit;
+#endif
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--stop-on-error"))
+ jsonReader.setStopOnErrorPolicy(OFTrue);
+ if (cmd.findOption("--ignore-errors"))
+ jsonReader.setStopOnErrorPolicy(OFFalse);
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--enable-new-vr"))
+ dcmEnableGenerationOfNewVRs();
+ if (cmd.findOption("--disable-new-vr"))
+ dcmDisableGenerationOfNewVRs();
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--length-explicit"))
+ opt_enctype = EET_ExplicitLength;
+ if (cmd.findOption("--length-undefined"))
+ opt_enctype = EET_UndefinedLength;
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--charset-accept"))
+ opt_replaceCharset = OFFalse;
+ if (cmd.findOption("--charset-replace"))
+ opt_replaceCharset = OFTrue;
+ cmd.endOptionBlock();
+
+#ifdef WITH_ZLIB
+ if (cmd.findOption("--compression-level"))
+ {
+ OFCmdUnsignedInt comprLevel = 0;
+ app.checkDependence("--compression-level", "--write-xfer-deflated", opt_xfer == EXS_DeflatedLittleEndianExplicit);
+ app.checkValue(cmd.getValueAndCheckMinMax(comprLevel, 0, 9));
+ dcmZlibCompressionLevel.set(OFstatic_cast(int, comprLevel));
+ }
+#endif
+
+ return EC_Normal;
+}
+
+void generateUIDs(DcmItem *dataset, OFBool overwriteUIDs, E_FileWriteMode& writeMode)
+{
+ char uid[100];
+ if (overwriteUIDs || !dataset->tagExistsWithValue(DCM_StudyInstanceUID))
+ {
+ OFLOG_INFO(json2dcmLogger, "generating new Study Instance UID");
+ dataset->putAndInsertString(DCM_StudyInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_STUDY_UID_ROOT));
+ }
+ if (overwriteUIDs || !dataset->tagExistsWithValue(DCM_SeriesInstanceUID))
+ {
+ OFLOG_INFO(json2dcmLogger, "generating new Series Instance UID");
+ dataset->putAndInsertString(DCM_SeriesInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT));
+ }
+ if (overwriteUIDs || !dataset->tagExistsWithValue(DCM_SOPInstanceUID))
+ {
+ OFLOG_INFO(json2dcmLogger, "generating new SOP Instance UID");
+ dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
+
+ /* make sure that the file meta information is updated correspondingly */
+ if (writeMode == EWM_fileformat)
+ writeMode = EWM_updateMeta;
+ }
+}
+
+void updateCharacterSet(DcmItem *dataset, const char *ifname, OFBool replaceCharset)
+{
+ OFString allowedCharset = "ISO_IR 192";
+ OFString asciiCharset = "ISO_IR 6";
+ const char *elemValue;
+ OFCondition result = dataset->findAndGetString(DCM_SpecificCharacterSet, elemValue, OFTrue /*searchIntoSub*/);
+ if (replaceCharset)
+ {
+ if (result.bad() || elemValue == NULL)
+ {
+ OFLOG_WARN(json2dcmLogger, "JSON file '" << ifname << "' does not specify a character set, it will be set to UTF-8 ('" << allowedCharset << "')");
+ dataset->putAndInsertString(DCM_SpecificCharacterSet, allowedCharset.c_str());
+ }
+ else if (allowedCharset.compare(elemValue) != 0)
+ {
+ OFLOG_WARN(json2dcmLogger, "JSON file '" << ifname << "' specifies a character set other than UTF-8, it will be set to UTF-8 ('" << allowedCharset << "')");
+ dataset->putAndInsertString(DCM_SpecificCharacterSet, allowedCharset.c_str());
+ }
+ }
+ else
+ {
+ if ((result.bad() || elemValue == NULL))
+ {
+ if (dataset->containsExtendedCharacters())
+ {
+ // JSON dataset contains non-ASCII characters but no specific character set
+ OFLOG_WARN(json2dcmLogger, "JSON file '" << ifname << "' does not specify a character set, the file is encoded in UTF-8 ('" << allowedCharset << "')");
+ }
+ }
+ else if (allowedCharset.compare(elemValue) != 0)
+ {
+ // JSON dataset specifies a specific character set other then ISO_IR 192
+ if (dataset->containsExtendedCharacters() || (asciiCharset.compare(elemValue) != 0))
+ {
+ // JSON dataset is not ASCII (ISO_IR 6) either
+ OFLOG_WARN(json2dcmLogger, "JSON file '" << ifname << "' specifies the character set '"
+ << elemValue << "' but the file is encoded in UTF-8 ('" << allowedCharset << "')");
+ }
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ OFBool opt_generateUIDs = OFFalse;
+ OFBool opt_overwriteUIDs = OFFalse;
+ E_TransferSyntax opt_xfer = EXS_Unknown;
+ E_EncodingType opt_enctype = EET_ExplicitLength;
+ OFBool opt_replaceCharset = OFFalse;
+ E_FileWriteMode opt_writeMode = EWM_fileformat;
+
+ const char *opt_ifname = NULL;
+ const char *opt_ofname = NULL;
+
+ /* set-up command line parameters and options */
+ OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, OFFIS_CONSOLE_DESCRIPTION, rcsid);
+ OFCommandLine cmd;
+
+ // add supported command line options
+ addJSON2DCMCommandlineOptions(cmd);
+
+ // evaluate command line
+ prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
+ if (app.parseCommandLine(cmd, argc, argv))
+ {
+ // checking exclusive options first
+ if (cmd.hasExclusiveOption())
+ {
+ if (cmd.findOption("--version"))
+ {
+ app.printHeader(OFTrue /*print host identifier*/);
+ COUT << OFendl << "External libraries used:";
+#ifdef WITH_ZLIB
+ COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
+#else
+ COUT << " none" << OFendl;
+#endif
+ return EXITCODE_NO_ERROR;
+ }
+ }
+ }
+
+ /* print resource identifier */
+ OFLOG_DEBUG(json2dcmLogger, rcsid << OFendl);
+
+ /* make sure data dictionary is loaded */
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFLOG_WARN(json2dcmLogger, "no data dictionary loaded, check environment variable: "
+ << DCM_DICT_ENVIRONMENT_VARIABLE);
+ }
+
+ DcmFileFormat fileformat;
+ DcmJSONReader jsonReader;
+
+ /* command line parameters and options */
+ OFCondition result = parseArguments(
+ app, cmd,
+ opt_generateUIDs,
+ opt_overwriteUIDs,
+ opt_xfer,
+ opt_enctype,
+ opt_replaceCharset,
+ opt_writeMode,
+ opt_ifname,
+ opt_ofname,
+ jsonReader
+ );
+
+ if (result.bad())
+ return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
+
+ // check filenames
+ if ((opt_ifname == NULL) || (strlen(opt_ifname) == 0))
+ {
+ OFLOG_ERROR(json2dcmLogger, OFFIS_CONSOLE_APPLICATION << ": invalid input filename: <empty string>");
+ return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
+ }
+ if ((opt_ofname == NULL) || (strlen(opt_ofname) == 0))
+ {
+ OFLOG_ERROR(json2dcmLogger, OFFIS_CONSOLE_APPLICATION << ": invalid output filename: <empty string>");
+ return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
+ }
+
+ // read JSON file and convert to DICOM
+ OFLOG_INFO(json2dcmLogger, "reading JSON input file: " << opt_ifname);
+ result = jsonReader.readAndConvertJSONFile(fileformat, opt_ifname);
+ if (result.bad())
+ {
+ if (result == EC_BulkDataURINotSupported)
+ return EXITCODE_BULKDATA_URI_NOT_SUPPORTED;
+ else if (result == EC_InvalidFilename)
+ return EXITCODE_CANNOT_READ_INPUT_FILE;
+ else
+ return EXITCODE_INVALID_JSON_CONTENT;
+ }
+
+ // generate new UIDs (if required)
+ if (opt_generateUIDs)
+ {
+ generateUIDs(fileformat.getDataset(), opt_overwriteUIDs, opt_writeMode);
+ }
+
+ // check and update SpecificCharacterSet
+ updateCharacterSet(fileformat.getDataset(), opt_ifname, opt_replaceCharset);
+
+ // determine the transfer syntax for writing the file
+ if (opt_xfer == EXS_Unknown)
+ {
+ /* use Explicit VR Little Endian as default if no transfer syntax is given otherwise */
+ if (jsonReader.getTransferSyntax() == EXS_Unknown)
+ opt_xfer = EXS_LittleEndianExplicit;
+ else
+ opt_xfer = jsonReader.getTransferSyntax();
+ }
+
+ // check whether it is possible to write the file in the requested transfer syntax
+ if (fileformat.canWriteXfer(opt_xfer))
+ {
+ // encapsulated pixel data requires a DICOM file, in this case ignore --write-dataset
+ if ((opt_writeMode == EWM_dataset) && DcmXfer(opt_xfer).usesEncapsulatedFormat())
+ {
+ OFLOG_WARN(json2dcmLogger, "encapsulated pixel data require file format, ignoring --write-dataset");
+ opt_writeMode = EWM_fileformat;
+ }
+
+ OFLOG_INFO(json2dcmLogger, "writing DICOM output file: " << opt_ofname);
+ result = fileformat.saveFile(opt_ofname, opt_xfer, opt_enctype, EGL_withoutGL, EPD_noChange,
+ OFstatic_cast(Uint32, 0), OFstatic_cast(Uint32, 0), opt_writeMode);
+
+ if (result.bad())
+ {
+ OFLOG_ERROR(json2dcmLogger, result.text() << ": writing file: " << opt_ofname);
+ return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+ }
+ }
+ else
+ {
+ OFLOG_ERROR(json2dcmLogger, "no conversion to transfer syntax " << DcmXfer(opt_xfer).getXferName() << " possible!");
+ return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+ }
+
+ return 0;
+}
+
{
opt_xfer = EXS_LittleEndianExplicit;
}
- /* write DICOM file */
+ /* write DICOM file. We deliberately use write mode EWM_fileformat here because
+ * EWM_createNewMeta would break the "--no-meta-uid" command line option
+ */
result = dfile->saveFile(file_name,
opt_xfer,
opt_enctype,
opt_padenc,
OFstatic_cast(Uint32, opt_filepad),
OFstatic_cast(Uint32, opt_itempad),
- (opt_dataset) ? EWM_dataset : EWM_createNewMeta);
+ (opt_dataset) ? EWM_dataset : EWM_fileformat);
}
else
{
/*
*
- * Copyright (C) 2005-2019, OFFIS e.V.
+ * Copyright (C) 2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* Module: dcmdata
*
- * Author: Marco Eichelberg, Pedro Arizpe
+ * Authors: Marco Eichelberg
*
- * Purpose: Encapsulate PDF file into a DICOM file
+ * Purpose: Proxy stub that calls dcmencap
*
*/
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#include "dcmtk/dcmdata/dctk.h"
-#include "dcmtk/dcmdata/dcencdoc.h"
-#include "dcmtk/ofstd/ofconapp.h"
+#include "dcmtk/ofstd/ofstub.h"
+#include "dcmtk/ofstd/ofstd.h"
+#include <cstring>
-#ifdef WITH_ZLIB
-#include <zlib.h> /* for zlibVersion() */
-#endif
-
-#define OFFIS_CONSOLE_APPLICATION "pdf2dcm"
-
-static OFLogger pdf2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
-
-static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
-OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
-
-int main(int argc, char *argv[])
+int main(int argc, char** argv)
{
- OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encapsulate PDF file into DICOM format", rcsid);
- OFCommandLine cmd;
- int errorCode = EXITCODE_NO_ERROR;
- OFCondition result = EC_Normal;
- DcmFileFormat fileformat;
- DcmEncapsulatedDocument encapsulator;
-
- OFLOG_TRACE(pdf2dcmLogger, "Including necessary options");
- encapsulator.addPDFCommandlineOptions(cmd);
- OFLOG_TRACE(pdf2dcmLogger, "Evaluating command line");
- prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
-
- if (app.parseCommandLine(cmd, argc, argv)) {
- OFLOG_TRACE(pdf2dcmLogger, "Checking exclusive options first");
- if (cmd.hasExclusiveOption())
- {
- if (cmd.findOption("--version"))
- {
- app.printHeader(OFTrue /*print host identifier*/);
- COUT << OFendl << "External libraries used: ";
-#ifdef WITH_ZLIB
- COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
-#else
- COUT << " none" << OFendl;
-#endif
- return EXITCODE_NO_ERROR;
- }
- }
- encapsulator.parseArguments(app, cmd);
- }
- //print resource identifier
- OFLOG_DEBUG(pdf2dcmLogger, rcsid << OFendl);
-
- OFLOG_DEBUG(pdf2dcmLogger, "making sure data dictionary is loaded");
- if (!dcmDataDict.isDictionaryLoaded())
- {
- OFLOG_WARN(pdf2dcmLogger, "no data dictionary loaded, check environment variable: "
- << DCM_DICT_ENVIRONMENT_VARIABLE);
- }
- OFLOG_DEBUG(pdf2dcmLogger, "Creating identifiers (and reading series data)");
- result = encapsulator.createIdentifiers(pdf2dcmLogger);
- if (result.bad())
- {
- OFLOG_FATAL(pdf2dcmLogger, "There was an error while reading the series data");
- return EXITCODE_INVALID_INPUT_FILE;
- }
- OFLOG_INFO(pdf2dcmLogger, "creating encapsulated PDF object");
- errorCode = encapsulator.insertEncapsulatedDocument(fileformat.getDataset(), pdf2dcmLogger);
- if (errorCode != EXITCODE_NO_ERROR)
- {
- OFLOG_ERROR(pdf2dcmLogger, "unable to create PDF encapsulation to DICOM format");
- return errorCode;
- }
- OFLOG_INFO(pdf2dcmLogger, "Generating an instance number that is guaranteed to be unique within a series.");
- result = encapsulator.createHeader(fileformat.getDataset(), pdf2dcmLogger);
- if (result.bad())
- {
- OFLOG_ERROR(pdf2dcmLogger, "unable to create DICOM header: " << result.text());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
- OFLOG_INFO(pdf2dcmLogger, "writing encapsulated PDF object as file " << encapsulator.getOutputFileName());
-
- OFLOG_INFO(pdf2dcmLogger, "Check if new output transfer syntax is possible");
-
- DcmXfer opt_oxferSyn(encapsulator.getTransferSyntax());
-
- fileformat.getDataset()->chooseRepresentation(encapsulator.getTransferSyntax(), NULL);
- if (fileformat.getDataset()->canWriteXfer(encapsulator.getTransferSyntax()))
- {
- OFLOG_INFO(pdf2dcmLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written");
- }
- else {
- OFLOG_ERROR(pdf2dcmLogger, "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- OFLOG_INFO(pdf2dcmLogger, "Checking for DICOM key overriding");
- result = encapsulator.applyOverrideKeys(fileformat.getDataset());
- if (result.bad())
- {
- OFLOG_ERROR(pdf2dcmLogger, "There was a problem while overriding a key:" << OFendl
- << result.text());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
- OFLOG_INFO(pdf2dcmLogger, "write converted DICOM file with metaheader");
- result = encapsulator.saveFile(fileformat);
- if (result.bad())
- {
- OFLOG_ERROR(pdf2dcmLogger, result.text() << ": writing file: " << encapsulator.getOutputFileName());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- OFLOG_INFO(pdf2dcmLogger, "PDF encapsulation successful");
-
- return EXITCODE_NO_ERROR;
+ // create an argv array that is one entry larger than the one specified by the user
+ char **my_argv = new char *[argc+2];
+ char filetype[100];
+ OFStandard::strlcpy(filetype, "--filetype-pdf", sizeof(filetype));
+
+ // copy arguments, then add file type argument and NULL pointer
+ memcpy(my_argv, argv, argc * sizeof(char *));
+ my_argv[argc] = filetype;
+ my_argv[argc+1] = NULL;
+
+ // call stub
+ int result = OFstub_main(argc+1, my_argv, "pdf2dcm", "dcmencap");
+
+ // clean up (Windows only, on Posix systems the stub will not return)
+ delete[] my_argv;
+ return result;
}
/*
*
- * Copyright (C) 2018-2019, OFFIS e.V.
+ * Copyright (C) 2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* Module: dcmdata
*
- * Author: Pedro Arizpe
+ * Authors: Marco Eichelberg
*
- * Purpose: Encapsulate STL file into a DICOM file
+ * Purpose: Proxy stub that calls dcmencap
*
*/
-#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first*/
-#include "dcmtk/dcmdata/dctk.h"
-#include "dcmtk/dcmdata/dcencdoc.h"
-#include "dcmtk/ofstd/ofconapp.h"
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/ofstub.h"
+#include "dcmtk/ofstd/ofstd.h"
+#include <cstring>
-#ifdef WITH_ZLIB
-#include <zlib.h> /* for zlibVersion() */
-#endif
-
-#define OFFIS_CONSOLE_APPLICATION "stl2dcm"
-
-static OFLogger stl2dcmLogger = OFLog::getLogger("dcmtk.apps." OFFIS_CONSOLE_APPLICATION);
-
-static char rcsid[] = "$dcmtk: " OFFIS_CONSOLE_APPLICATION " v"
-OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
-
-int main(int argc, char *argv[])
+int main(int argc, char** argv)
{
- OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Encapsulate STL file into DICOM format", rcsid);
- OFCommandLine cmd;
- int errorCode = EXITCODE_NO_ERROR;
- OFCondition result = EC_Normal;
- DcmFileFormat fileformat;
- DcmEncapsulatedDocument encapsulator;
-
- OFLOG_TRACE(stl2dcmLogger, "Including necessary options");
- encapsulator.addSTLCommandlineOptions(cmd);
- OFLOG_TRACE(stl2dcmLogger, "Evaluating command line");
- prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
-
- if (app.parseCommandLine(cmd, argc, argv)) {
- OFLOG_TRACE(stl2dcmLogger, "Checking exclusive options first");
- if (cmd.hasExclusiveOption())
- {
- if (cmd.findOption("--version"))
- {
- app.printHeader(OFTrue /*print host identifier*/);
- COUT << OFendl << "External libraries used: ";
-#ifdef WITH_ZLIB
- COUT << OFendl << "- ZLIB, Version " << zlibVersion() << OFendl;
-#else
- COUT << " none" << OFendl;
-#endif
- return EXITCODE_NO_ERROR;
- }
- }
- encapsulator.parseArguments(app, cmd);
- }
- //print resource identifier
- OFLOG_DEBUG(stl2dcmLogger, rcsid << OFendl);
-
- OFLOG_DEBUG(stl2dcmLogger, "making sure data dictionary is loaded");
- if (!dcmDataDict.isDictionaryLoaded())
- {
- OFLOG_WARN(stl2dcmLogger, "no data dictionary loaded, check environment variable: "
- << DCM_DICT_ENVIRONMENT_VARIABLE);
- }
- OFLOG_DEBUG(stl2dcmLogger, "Creating identifiers (and reading series data)");
- result = encapsulator.createIdentifiers(stl2dcmLogger);
- if (result.bad())
- {
- OFLOG_FATAL(stl2dcmLogger, "There was an error while reading the series data");
- return EXITCODE_INVALID_INPUT_FILE;
- }
- OFLOG_INFO(stl2dcmLogger, "creating encapsulated STL object");
- errorCode = encapsulator.insertEncapsulatedDocument(fileformat.getDataset(), stl2dcmLogger);
- if (errorCode != EXITCODE_NO_ERROR)
- {
- OFLOG_ERROR(stl2dcmLogger, "unable to create STL encapsulation to DICOM format");
- return errorCode;
- }
- OFLOG_INFO(stl2dcmLogger, "Generating an instance number that is guaranteed to be unique within a series.");
- result = encapsulator.createHeader(fileformat.getDataset(), stl2dcmLogger);
- if (result.bad())
- {
- OFLOG_ERROR(stl2dcmLogger, "unable to create DICOM header: " << result.text());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
- OFLOG_INFO(stl2dcmLogger, "writing encapsulated STL object as file " << encapsulator.getOutputFileName());
-
- OFLOG_INFO(stl2dcmLogger, "Check if new output transfer syntax is possible");
-
- DcmXfer opt_oxferSyn(encapsulator.getTransferSyntax());
-
- fileformat.getDataset()->chooseRepresentation(encapsulator.getTransferSyntax(), NULL);
- if (fileformat.getDataset()->canWriteXfer(encapsulator.getTransferSyntax()))
- {
- OFLOG_INFO(stl2dcmLogger, "Output transfer syntax " << opt_oxferSyn.getXferName() << " can be written");
- }
- else {
- OFLOG_ERROR(stl2dcmLogger, "No conversion to transfer syntax " << opt_oxferSyn.getXferName() << " possible!");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- OFLOG_INFO(stl2dcmLogger, "Checking for DICOM key overriding");
- result = encapsulator.applyOverrideKeys(fileformat.getDataset());
- if (result.bad())
- {
- OFLOG_ERROR(stl2dcmLogger, "There was a problem while overriding a key:" << OFendl
- << result.text());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
- OFLOG_INFO(stl2dcmLogger, "write converted DICOM file with metaheader");
- result = encapsulator.saveFile(fileformat);
- if (result.bad())
- {
- OFLOG_ERROR(stl2dcmLogger, result.text() << ": writing file: " << encapsulator.getOutputFileName());
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
-
- OFLOG_INFO(stl2dcmLogger, "STL encapsulation successful");
-
- return EXITCODE_NO_ERROR;
+ // create an argv array that is one entry larger than the one specified by the user
+ char **my_argv = new char *[argc+2];
+ char filetype[100];
+ OFStandard::strlcpy(filetype, "--filetype-stl", sizeof(filetype));
+
+ // copy arguments, then add file type argument and NULL pointer
+ memcpy(my_argv, argv, argc * sizeof(char *));
+ my_argv[argc] = filetype;
+ my_argv[argc+1] = NULL;
+
+ // call stub
+ int result = OFstub_main(argc+1, my_argv, "stl2dcm", "dcmencap");
+
+ // clean up (Windows only, on Posix systems the stub will not return)
+ delete[] my_argv;
+ return result;
}
#
-# Copyright (C) 1994-2024, OFFIS e.V.
+# Copyright (C) 1994-2025, OFFIS e.V.
# All rights reserved. See COPYRIGHT file for details.
#
# This software and supporting documentation were developed by
# DICONDE (Digital Imaging and Communication in Nondestructive Evaluation) and
# DICOS (Digital Imaging and Communications in Security) standard.
#
-# Generated automatically from DICOM PS 3.6-2024e and PS 3.7-2024e.
-# File created on 2024-11-16 10:17:21 by J. Riesmeier on thinkpad2.
+# Generated automatically from DICOM PS 3.6-2025e and PS 3.7-2025e.
+# File created on 2025-11-21 11:51:05 by J. Riesmeier on thinkpad2.
#
# In addition, the data dictionary entries from the following final text
# supplements and correction items (CP) have been incorporated:
(0008,119B) SQ FailedStudySequence 1 DICOM
(0008,1200) SQ StudiesContainingOtherReferencedInstancesSequence 1 DICOM
(0008,1250) SQ RelatedSeriesSequence 1 DICOM
+(0008,1301) SQ PrincipalDiagnosisCodeSequence 1 DICOM
+(0008,1302) SQ PrimaryDiagnosisCodeSequence 1 DICOM
+(0008,1303) SQ SecondaryDiagnosesCodeSequence 1 DICOM
+(0008,1304) SQ HistologicalDiagnosesCodeSequence 1 DICOM
(0008,2111) ST DerivationDescription 1 DICOM
(0008,2112) SQ SourceImageSequence 1 DICOM
(0008,2120) SH StageName 1 DICOM
(0008,9459) FL RecommendedDisplayFrameRateInFloat 1 DICOM
(0008,9460) CS SkipFrameRangeFlag 1 DICOM
(0010,0010) PN PatientName 1 DICOM
+(0010,0011) SQ PersonNamesToUseSequence 1 DICOM
+(0010,0012) LT NameToUse 1 DICOM
+(0010,0013) UT NameToUseComment 1 DICOM
+(0010,0014) SQ ThirdPersonPronounsSequence 1 DICOM
+(0010,0015) SQ PronounCodeSequence 1 DICOM
+(0010,0016) UT PronounComment 1 DICOM
(0010,0020) LO PatientID 1 DICOM
(0010,0021) LO IssuerOfPatientID 1 DICOM
(0010,0022) CS TypeOfPatientID 1 DICOM
(0010,0034) LO PatientDeathDateInAlternativeCalendar 1 DICOM
(0010,0035) CS PatientAlternativeCalendar 1 DICOM
(0010,0040) CS PatientSex 1 DICOM
+(0010,0041) SQ GenderIdentitySequence 1 DICOM
+(0010,0042) UT SexParametersForClinicalUseCategoryComment 1 DICOM
+(0010,0043) SQ SexParametersForClinicalUseCategorySequence 1 DICOM
+(0010,0044) SQ GenderIdentityCodeSequence 1 DICOM
+(0010,0045) UT GenderIdentityComment 1 DICOM
+(0010,0046) SQ SexParametersForClinicalUseCategoryCodeSequence 1 DICOM
+(0010,0047) UR SexParametersForClinicalUseCategoryReference 1-n DICOM
(0010,0050) SQ PatientInsurancePlanCodeSequence 1 DICOM
(0010,0101) SQ PatientPrimaryLanguageCodeSequence 1 DICOM
(0010,0102) SQ PatientPrimaryLanguageModifierCodeSequence 1 DICOM
(0010,2152) LO RegionOfResidence 1 DICOM
(0010,2154) SH PatientTelephoneNumbers 1-n DICOM
(0010,2155) LT PatientTelecomInformation 1 DICOM
-(0010,2160) SH EthnicGroup 1 DICOM
(0010,2161) SQ EthnicGroupCodeSequence 1 DICOM
+(0010,2162) UC EthnicGroups 1-n DICOM
(0010,2180) SH Occupation 1 DICOM
(0010,21A0) CS SmokingStatus 1 DICOM
(0010,21B0) LT AdditionalPatientHistory 1 DICOM
(0014,40A0) LO ImageQualityIndicatorType 1-n DICOM/DICONDE
(0014,40A1) LO ImageQualityIndicatorMaterial 1-n DICOM/DICONDE
(0014,40A2) LO ImageQualityIndicatorSize 1-n DICOM/DICONDE
+(0014,4101) SQ WaveDimensionsDefinitionSequence 1 DICOM/DICONDE
+(0014,4102) US WaveDimensionNumber 1 DICOM/DICONDE
+(0014,4103) LO WaveDimensionDescription 1 DICOM/DICONDE
+(0014,4104) US WaveDimensionUnit 1 DICOM/DICONDE
+(0014,4105) CS WaveDimensionValueType 1 DICOM/DICONDE
+(0014,4106) SQ WaveDimensionValuesSequence 1-n DICOM/DICONDE
+(0014,4107) US ReferencedWaveDimension 1 DICOM/DICONDE
+(0014,4108) SL IntegerNumericValue 1 DICOM/DICONDE
+(0014,4109) OB ByteNumericValue 1 DICOM/DICONDE
+(0014,410A) OW ShortNumericValue 1 DICOM/DICONDE
+(0014,410B) OF SinglePrecisionFloatingPointNumericValue 1 DICOM/DICONDE
+(0014,410C) OD DoublePrecisionFloatingPointNumericValue 1 DICOM/DICONDE
(0014,5002) IS LINACEnergy 1 DICOM/DICONDE
(0014,5004) IS LINACOutput 1 DICOM/DICONDE
(0014,5100) US ActiveAperture 1 DICOM/DICONDE
(0040,A030) DT VerificationDateTime 1 DICOM
(0040,A032) DT ObservationDateTime 1 DICOM
(0040,A033) DT ObservationStartDateTime 1 DICOM
+(0040,A034) DT EffectiveStartDateTime 1 DICOM
+(0040,A035) DT EffectiveStopDateTime 1 DICOM
(0040,A040) CS ValueType 1 DICOM
(0040,A043) SQ ConceptNameCodeSequence 1 DICOM
(0040,A050) CS ContinuityOfContent 1 DICOM
(0040,A807) SQ TableColumnDefinitionSequence 1 DICOM
(0040,A808) SQ CellValuesSequence 1 DICOM
(0040,B020) SQ WaveformAnnotationSequence 1 DICOM
+(0040,B030) SQ StructuredWaveformAnnotationSequence 1 DICOM
+(0040,B031) SQ WaveformAnnotationDisplaySelectionSequence 1 DICOM
+(0040,B032) US ReferencedMontageIndex 1 DICOM
+(0040,B033) SQ WaveformTextualAnnotationSequence 1 DICOM
+(0040,B034) DT AnnotationDateTime 1 DICOM
+(0040,B035) SQ DisplayedWaveformSegmentSequence 1 DICOM
+(0040,B036) DT SegmentDefinitionDateTime 1 DICOM
+(0040,B037) SQ MontageActivationSequence 1 DICOM
+(0040,B038) DS MontageActivationTimeOffset 1 DICOM
+(0040,B039) SQ WaveformMontageSequence 1 DICOM
+(0040,B03A) IS ReferencedMontageChannelNumber 1 DICOM
+(0040,B03B) LT MontageName 1 DICOM
+(0040,B03C) SQ MontageChannelSequence 1 DICOM
+(0040,B03D) US MontageIndex 1 DICOM
+(0040,B03E) IS MontageChannelNumber 1 DICOM
+(0040,B03F) LO MontageChannelLabel 1 DICOM
+(0040,B040) SQ MontageChannelSourceCodeSequence 1 DICOM
+(0040,B041) SQ ContributingChannelSourcesSequence 1 DICOM
+(0040,B042) FL ChannelWeight 1 DICOM
(0040,DB00) CS TemplateIdentifier 1 DICOM
(0040,DB73) UL ReferencedContentItemIdentifier 1-n DICOM
(0040,E001) ST HL7InstanceIdentifier 1 DICOM
(0044,0108) UI ReferencedAssertionUID 1 DICOM
(0044,0109) SQ ApprovalSubjectSequence 1 DICOM
(0044,010A) SQ OrganizationalRoleCodeSequence 1 DICOM
+(0044,0110) SQ RTAssertionsSequence 1 DICOM
(0046,0012) LO LensDescription 1 DICOM
(0046,0014) SQ RightLensSequence 1 DICOM
(0046,0015) SQ LeftLensSequence 1 DICOM
(0048,0301) CS PixelOriginInterpretation 1 DICOM
(0048,0302) UL NumberOfOpticalPaths 1 DICOM
(0048,0303) UL TotalPixelMatrixFocalPlanes 1 DICOM
+(0048,0304) CS TilesOverlap 1 DICOM
(0050,0004) CS CalibrationImage 1 DICOM
(0050,0010) SQ DeviceSequence 1 DICOM
(0050,0012) SQ ContainerComponentTypeCodeSequence 1 DICOM
(3004,0070) DS DVHMinimumDose 1 DICOM
(3004,0072) DS DVHMaximumDose 1 DICOM
(3004,0074) DS DVHMeanDose 1 DICOM
+(3004,0080) SQ DoseCalculationModelSequence 1 DICOM
+(3004,0081) SQ DoseCalculationAlgorithmSequence 1 DICOM
+(3004,0082) CS CommissioningStatus 1 DICOM
+(3004,0083) SQ DoseCalculationModelParameterSequence 1 DICOM
+(3004,0084) CS DoseDepositionCalculationMedium 1 DICOM
(3006,0002) SH StructureSetLabel 1 DICOM
(3006,0004) LO StructureSetName 1 DICOM
(3006,0006) ST StructureSetDescription 1 DICOM
(300A,0398) FL ScanningSpotSize 2 DICOM
(300A,0399) FL ScanSpotSizesDelivered 2-2n DICOM
(300A,039A) IS NumberOfPaintings 1 DICOM
+(300A,039B) FL ScanSpotGantryAngles 1-n DICOM
+(300A,039C) FL ScanSpotPatientSupportAngles 1-n DICOM
(300A,03A0) SQ IonToleranceTableSequence 1 DICOM
(300A,03A2) SQ IonBeamSequence 1 DICOM
(300A,03A4) SQ IonBeamLimitingDeviceSequence 1 DICOM
(0010,1000) LO RETIRED_OtherPatientIDs 1-n DICOM/retired
(0010,1050) LO RETIRED_InsurancePlanIdentification 1-n DICOM/retired
(0010,1090) LO RETIRED_MedicalRecordLocator 1 DICOM/retired
+(0010,2160) SH RETIRED_EthnicGroup 1 DICOM/retired
(0014,0023) ST RETIRED_CADFileFormat 1 DICOM/retired
(0014,0024) ST RETIRED_ComponentReferenceSystem 1 DICOM/retired
(0014,0045) ST RETIRED_MaterialPropertiesFileFormatRetired 1 DICOM/retired
(7F00-7FFF,0020) OW RETIRED_VariableCoefficientsSDVN 1 DICOM/retired
(7F00-7FFF,0030) OW RETIRED_VariableCoefficientsSDHN 1 DICOM/retired
(7F00-7FFF,0040) OW RETIRED_VariableCoefficientsSDDN 1 DICOM/retired
-(7F00-7FFF,0040) OW RETIRED_VariableCoefficientsSDDN 1 DICOM/retired
#
#---------------------------------------------------------------------------
#
\section cda2dcm_description DESCRIPTION
-The \b cda2dcm utility reads a CDA file (\e cdafile-in), converts it to a
-DICOM Encapsulated CDA Storage SOP instance and stores the converted data
-to an output file (\e dcmfile-out).
+The \b cda2dcm tool is deprecated. Use \b dcmencap instead, which supports
+the same command line parameters, and more.
-\section cda2dcm_parameters PARAMETERS
+\section cda2dcm_see_also SEE ALSO
-\verbatim
-cdafile-in CDA input filename to be encapsulated
-
-dcmfile-out DICOM output filename ("-" for stdout)
-\endverbatim
-
-\section cda2dcm_options OPTIONS
-
-\subsection cda2dcm_general_options general options
-\verbatim
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-\endverbatim
-
-\subsection cda2dcm_dicom_document_options DICOM document options
-\verbatim
-document title:
-
- +t --title [t]itle: string (default: empty)
- document title
-
- +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
- coded representation of document title defined by coding
- scheme designator CSD, code value CV and code meaning CM
-
-patient data:
-
- +pn --patient-name [n]ame: string
- patient's name in DICOM PN syntax
-
- +pi --patient-id [i]d: string
- patient identifier
-
- +pb --patient-birthdate [d]ate: string (YYYYMMDD)
- patient's birth date
-
- +ps --patient-sex [s]ex: string (M, F or O)
- patient's sex
-
-study and series:
-
- +sg --generate
- generate new study and series UIDs (default)
-
- +st --study-from [f]ilename: string
- read patient/study data from DICOM file
-
- +se --series-from [f]ilename: string
- read patient/study/series data from DICOM file
-
-instance number:
-
- +i1 --instance-one
- use instance number 1 (default, not with +se)
-
- +ii --instance-inc
- increment instance number (only with +se)
-
- +is --instance-set [i]nstance number: integer
- use instance number i
-
-burned-in annotation:
-
- +an --annotation-yes
- document contains patient identifying data (default)
-
- -an --annotation-no
- document does not contain patient identifying data
-
-override CDA file data:
-
- -ov --no-override
- CDA patient and document data must match study,
- series or manually entered information (default)
-
- +ov --override
- data obtained from the CDA file will be overwritten
- by study, series, or manually entered information
-\endverbatim
-
-\subsection cda2dcm_processing_options processing options
-\verbatim
-other processing options:
-
- -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
- add further attribute
-\endverbatim
-
-\subsection cda2dcm_output_options output options
-\verbatim
-output file format:
-
- +F --write-file
- write file format (default)
-
- -F --write-dataset
- write data set without file meta information
-
-group length encoding:
-
- +g= --group-length-recalc
- recalculate group lengths if present (default)
-
- +g --group-length-create
- always write with group length elements
-
- -g --group-length-remove
- always write without group length elements
-
-length encoding in sequences and items:
-
- +e --length-explicit
- write with explicit lengths (default)
-
- -e --length-undefined
- write with undefined lengths
-
-data set trailing padding (not with --write-dataset):
-
- -p --padding-off
- no padding (implicit if --write-dataset)
-
- +p --padding-create [f]ile-pad [i]tem-pad: integer
- align file on multiple of f bytes
- and items on multiple of i bytes
-\endverbatim
-
-\section cda2dcm_notes NOTES
-
-\subsection cda2dcm_attribute_sources Attribute Sources
-
-The application may be fed with some additional input for filling mandatory (and
-optional) attributes in the new DICOM file like patient, study and series
-information:
-
-- The \e --key option can be used to add further attributes to the DICOM output
- file.
-
-- It is also possible to specify sequences, items and nested attributes using
- the \e --key option. In these cases, a special "path" notation has to be
- used. Details on this path notation can be found in the documentation of
- \b dcmodify.
-
-- The \e --key option can be present more than once.
-
-- The value part (after the '=') may be absent causing the attribute to be set
- with zero length.
-
-- Please be advised that the \e --key option is applied at the very end, just
- before saving the DICOM file, so there is no value checking whatsoever.
-
-\section cda2dcm_logging LOGGING
-
-The level of logging output of the various command line tools and underlying
-libraries can be specified by the user. By default, only errors and warnings
-are written to the standard error stream. Using option \e --verbose also
-informational messages like processing details are reported. Option
-\e --debug can be used to get more details on the internal activity, e.g. for
-debugging purposes. Other logging levels can be selected using option
-\e --log-level. In \e --quiet mode only fatal errors are reported. In such
-very severe error events, the application will usually terminate. For more
-details on the different logging levels, see documentation of module "oflog".
-
-In case the logging output should be written to file (optionally with logfile
-rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
-can be used. This configuration file also allows for directing only certain
-messages to a particular output stream and for filtering certain messages
-based on the module or application where they are generated. An example
-configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
-
-\section cda2dcm_command_line COMMAND LINE
-
-All command line tools use the following notation for parameters: square
-brackets enclose optional values (0-1), three trailing dots indicate that
-multiple values are allowed (1-n), a combination of both means 0 to n values.
-
-Command line options are distinguished from parameters by a leading '+' or '-'
-sign, respectively. Usually, order and position of command line options are
-arbitrary (i.e. they can appear anywhere). However, if options are mutually
-exclusive the rightmost appearance is used. This behavior conforms to the
-standard evaluation rules of common Unix shells.
-
-In addition, one or more command files can be specified using an '@' sign as a
-prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
-is replaced by the content of the corresponding text file (multiple
-whitespaces are treated as a single separator unless they appear between two
-quotation marks) prior to any further evaluation. Please note that a command
-file cannot contain another command file. This simple but effective approach
-allows one to summarize common combinations of options/parameters and avoids
-longish and confusing command lines (an example is provided in file
-<em>\<datadir\>/dumppat.txt</em>).
-
-\section cda2dcm_exit_codes EXIT CODES
-
-The \b cda2dcm utility uses the following exit codes when terminating. This
-enables the user to check for the reason why the application terminated.
-
-\subsection cda2dcm_exit_codes_general general
-\verbatim
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-EXITCODE_MEMORY_EXHAUSTED 4
-\endverbatim
-
-\subsection cda2dcm_exit_codes_input_file_errors input file errors
-\verbatim
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-\endverbatim
-
-\subsection cda2dcm_exit_codes_output_file_errors output file errors
-\verbatim
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-\endverbatim
-
-\section cda2dcm_environment ENVIRONMENT
-
-The \b cda2dcm utility will attempt to load DICOM data dictionaries specified
-in the \e DCMDICTPATH environment variable. By default, i.e. if the
-\e DCMDICTPATH environment variable is not set, the file
-<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
-into the application (default for Windows).
-
-The default behavior should be preferred and the \e DCMDICTPATH environment
-variable only used when alternative data dictionaries are required. The
-\e DCMDICTPATH environment variable has the same format as the Unix shell
-\e PATH variable in that a colon (":") separates entries. On Windows systems,
-a semicolon (";") is used as a separator. The data dictionary code will
-attempt to load each file specified in the \e DCMDICTPATH environment
-variable.
-It is an error if no data dictionary can be loaded.
+<b>dcmencap</b>(1)
\section cda2dcm_copyright COPYRIGHT
-Copyright (C) 2018-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2018-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcm2cda_description DESCRIPTION
-The \b dcm2cda utility reads a DICOM file of the Encapsulated CDA Storage SOP
-Class (\e dcmfile-in), extracts the embedded CDA document and writes it to an
-output file (\e cdafile-out). Optionally a command can be executed after the
-creation of the CDA file.
-
-\section dcm2cda_parameters PARAMETERS
-
-\verbatim
-dcmfile-in DICOM input filename ("-" for stdin)
-
-cdafile-out CDA output filename
-\endverbatim
-
-\section dcm2cda_options OPTIONS
-
-\subsection dcm2cda_general_options general options
-\verbatim
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-\endverbatim
-
-\subsection dcm2cda_input_options input options
-\verbatim
-input file format:
-
- +f --read-file
- read file format or data set (default)
-
- +fo --read-file-only
- read file format only
-
- -f --read-dataset
- read data set without file meta information
-
-input transfer syntax:
-
- -t= --read-xfer-auto
- use TS recognition (default)
-
- -td --read-xfer-detect
- ignore TS specified in the file meta header
-
- -te --read-xfer-little
- read with explicit VR little endian TS
-
- -tb --read-xfer-big
- read with explicit VR big endian TS
-
- -ti --read-xfer-implicit
- read with implicit VR little endian TS
-
-parsing of odd-length attributes:
-
- +ao --accept-odd-length
- accept odd length attributes (default)
-
- +ae --assume-even-length
- assume real length is one byte larger
-
-handling of undefined length UN elements:
-
- +ui --enable-cp246
- read undefined len UN as implicit VR (default)
-
- -ui --disable-cp246
- read undefined len UN as explicit VR
-
-handling of defined length UN elements:
-
- -uc --retain-un
- retain elements as UN (default)
-
- +uc --convert-un
- convert to real VR if known
-
-automatic data correction:
-
- +dc --enable-correction
- enable automatic data correction (default)
-
- -dc --disable-correction
- disable automatic data correction
-
-bitstream format of deflated input:
-
- +bd --bitstream-deflated
- expect deflated bitstream (default)
-
- +bz --bitstream-zlib
- expect deflated zlib bitstream
-\endverbatim
-
-\section dcm2cda_logging LOGGING
-
-The level of logging output of the various command line tools and underlying
-libraries can be specified by the user. By default, only errors and warnings
-are written to the standard error stream. Using option \e --verbose also
-informational messages like processing details are reported. Option
-\e --debug can be used to get more details on the internal activity, e.g. for
-debugging purposes. Other logging levels can be selected using option
-\e --log-level. In \e --quiet mode only fatal errors are reported. In such
-very severe error events, the application will usually terminate. For more
-details on the different logging levels, see documentation of module "oflog".
-
-In case the logging output should be written to file (optionally with logfile
-rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
-can be used. This configuration file also allows for directing only certain
-messages to a particular output stream and for filtering certain messages
-based on the module or application where they are generated. An example
-configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
-
-\section dcm2cda_exit_codes EXIT CODES
-
-The \b dcm2cda utility uses the following exit codes when terminating. This
-enables the user to check for the reason why the application terminated.
-
-\subsection dcm2cda_exit_codes_general general
-\verbatim
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-\endverbatim
-
-\subsection dcm2cda_exit_codes_input_file_errors input file errors
-\verbatim
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-\endverbatim
-
-\subsection dcm2cda_exit_codes_output_file_errors output file errors
-\verbatim
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-\endverbatim
-
-\section dcm2cda_command_line COMMAND LINE
-
-All command line tools use the following notation for parameters: square
-brackets enclose optional values (0-1), three trailing dots indicate that
-multiple values are allowed (1-n), a combination of both means 0 to n values.
-
-Command line options are distinguished from parameters by a leading '+' or '-'
-sign, respectively. Usually, order and position of command line options are
-arbitrary (i.e. they can appear anywhere). However, if options are mutually
-exclusive the rightmost appearance is used. This behavior conforms to the
-standard evaluation rules of common Unix shells.
-
-In addition, one or more command files can be specified using an '@' sign as a
-prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
-is replaced by the content of the corresponding text file (multiple
-whitespaces are treated as a single separator unless they appear between two
-quotation marks) prior to any further evaluation. Please note that a command
-file cannot contain another command file. This simple but effective approach
-allows one to summarize common combinations of options/parameters and avoids
-longish and confusing command lines (an example is provided in file
-<em>\<datadir\>/dumppat.txt</em>).
-
-\section dcm2cda_environment ENVIRONMENT
-
-The \b dcm2cda utility will attempt to load DICOM data dictionaries specified
-in the \e DCMDICTPATH environment variable. By default, i.e. if the
-\e DCMDICTPATH environment variable is not set, the file
-<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
-into the application (default for Windows).
-
-The default behavior should be preferred and the \e DCMDICTPATH environment
-variable only used when alternative data dictionaries are required. The
-\e DCMDICTPATH environment variable has the same format as the Unix shell
-\e PATH variable in that a colon (":") separates entries. On Windows systems,
-a semicolon (";") is used as a separator. The data dictionary code will
-attempt to load each file specified in the \e DCMDICTPATH environment variable.
-It is an error if no data dictionary can be loaded.
+The \b dcm2cda tool is deprecated. Use \b dcmdecap instead, which supports
+the same command line parameters, and more.
\section dcm2cda_see_also SEE ALSO
-<b>cda2dcm</b>(1)
+<b>dcmdecap</b>(1)
\section dcm2cda_copyright COPYRIGHT
-Copyright (C) 2023-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2023-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
-is --is-ds-string
always encode as string
+
+bulk data URI options:
+
+ -b --bulk-disabled
+ write everything as inline binary (default)
+
+ +b --bulk-enabled
+ write large attributes as bulk data
+
+ +bz --bulk-size [s]ize: integer (default: 1)
+ use bulk data for attributes >= s kBytes
+
+ +bp --bulk-uri-prefix [u]ri prefix: string
+ use prefix u when generating bulk data URIs (default: file URI)
+
+ +bd --bulk-dir [d]irectory: string
+ write bulk data files to d (default: '.')
+
+ +bs --bulk-subdir
+ create subdirectory for each SOP instance
+ (default: no subdirectory)
\endverbatim
\subsection dcm2json_output_options output options
\subsection dcm2json_bulk_data Bulk Data
-Binary data, i.e. DICOM element values with Value Representations (VR) of OB
-or OW, as well as OD, OF, OL, OV and UN values are always written as
-"InlineBinary" (base64 encoding) to the JSON output. A future version of this
-tool might optionally use a "BulkDataURI" instead, i.e. the WADO-RS URL of a
-bulk data item that contains the element value. This would be particularly
-useful for large amounts of data, such as pixel data.
+By default, binary data, i.e. DICOM element values with Value Representations
+(VR) of OB, OD, OF, OL, OV, OW, and UN values are written as "InlineBinary"
+(base64 encoding) to the JSON output. Option \e --bulk-enabled causes binary
+data as well as DS, FD, FL, IS, SV and UV to be replaced by "BulkDataURI"
+values if the element value is larger than the cut-off threshold (default: 1
+kByte). The cut-off threshold can be specified with the \e --bulk-size option.
+The element values themselves are written as files to the directory given by
+the \e --bulk-dir option (default: current directory). The filename is based
+on a SHA-256 checksum of the element value. By default, file URIs are
+generated that point to the bulk directory. For production use, a URI prefix
+for a WADO-RS service over which the element values can be retrieved should be
+specified using the \e --bulk-uri-prefix option. This can be implemented by
+configuring a web server that has read access to \b dcm2json's bulk directory.
+Finally, the option \e --bulk-subdir will cause a separate subdirectory to be
+created (and used in the bulk data URI) for each distinct SOP instance.
+
+Note that the JSON syntax for the representation of encapsulated pixel data
+in "InlineBinary" form is unspecified in DICOM, as is the JSON representation
+of encapsulated multi-frame pixel data. These DICOM files cannot be converted
+to JSON using \b dcm2json.
+
+The file name extension for the bulk data files generated can be used to
+determine the MIME type that should be returned by the WADO-RS server:
+
+\verbatim
+ Extension MIME Type
+
+ .bin application/octet-stream
+ .jpeg image/jpeg
+ .dicom-rle image/dicom-rle
+ .jls image/jls
+ .jp2 image/jp2
+ .jpx image/jpx
+ .jphc image/jphc
+ .jxl image/jxl
+ .mpeg video/mpeg
+ .mp4 video/mp4
+ .H265 video/H265
+\endverbatim
+
+Finally, it should be noted that bulk data will be written "as is", i.e.
+\b dcm2json will not attempt to validate or modify the element value in any
+way. For example, \b dcm2json will not add a JFIF header in the case of JPEG
+baseline compressed images, which some JPEG viewers may expect.
\section dcm2json_notes NOTES
\subsection dcm2json_character_encoding Character Encoding
As required by the DICOM JSON encoding, \b dcm2json always creates output in
-Unicode UTF-8 encoding and converts DICOM datasets accordingly. If this is not
-possible, for example because DCMTK has been compiled without character set
+Unicode UTF-8 encoding and converts DICOM data sets accordingly. If this is
+not possible, for example because DCMTK has been compiled without character set
conversion support, an error is returned.
\section dcm2json_logging LOGGING
\section dcm2json_copyright COPYRIGHT
-Copyright (C) 2016-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2016-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcm2pdf_description DESCRIPTION
-The \b dcm2pdf utility reads a DICOM file of the Encapsulated PDF Storage SOP
-Class (\e dcmfile-in), extracts the embedded PDF document and writes it to an
-output file (\e pdffile-out). Optionally a command can be executed after the
-creation of the PDF file.
-
-\section dcm2pdf_parameters PARAMETERS
-
-\verbatim
-dcmfile-in DICOM input filename ("-" for stdin)
-
-pdffile-out PDF output filename
-\endverbatim
-
-\section dcm2pdf_options OPTIONS
-
-\subsection dcm2pdf_general_options general options
-\verbatim
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-\endverbatim
-
-\subsection dcm2pdf_input_options input options
-\verbatim
-input file format:
-
- +f --read-file
- read file format or data set (default)
-
- +fo --read-file-only
- read file format only
-
- -f --read-dataset
- read data set without file meta information
-
-input transfer syntax:
-
- -t= --read-xfer-auto
- use TS recognition (default)
-
- -td --read-xfer-detect
- ignore TS specified in the file meta header
-
- -te --read-xfer-little
- read with explicit VR little endian TS
-
- -tb --read-xfer-big
- read with explicit VR big endian TS
-
- -ti --read-xfer-implicit
- read with implicit VR little endian TS
-
-parsing of odd-length attributes:
-
- +ao --accept-odd-length
- accept odd length attributes (default)
-
- +ae --assume-even-length
- assume real length is one byte larger
-
-handling of undefined length UN elements:
-
- +ui --enable-cp246
- read undefined len UN as implicit VR (default)
-
- -ui --disable-cp246
- read undefined len UN as explicit VR
-
-handling of defined length UN elements:
-
- -uc --retain-un
- retain elements as UN (default)
-
- +uc --convert-un
- convert to real VR if known
-
-automatic data correction:
-
- +dc --enable-correction
- enable automatic data correction (default)
-
- -dc --disable-correction
- disable automatic data correction
-
-bitstream format of deflated input:
-
- +bd --bitstream-deflated
- expect deflated bitstream (default)
-
- +bz --bitstream-zlib
- expect deflated zlib bitstream
-\endverbatim
-
-\subsection dcm2pdf_processing_options processing options
-execution options:
-\verbatim
- -x --exec [c]ommand: string
- execute command c after PDF extraction
-\endverbatim
-
-\section dcm2pdf_notes NOTES
-
-Option \e --exec allows for the execution of a certain command line after the
-creation of the PDF document. The command line to be executed is passed to
-this option as a parameter. The specified command line may contain the
-placeholder '\#f', which will be replaced by the PDF filename at run time.
-The specified command line is executed in the foreground, i.e. \b pdf2dcm will
-be blocked until the command terminates.
-
-\section dcm2pdf_logging LOGGING
-
-The level of logging output of the various command line tools and underlying
-libraries can be specified by the user. By default, only errors and warnings
-are written to the standard error stream. Using option \e --verbose also
-informational messages like processing details are reported. Option
-\e --debug can be used to get more details on the internal activity, e.g. for
-debugging purposes. Other logging levels can be selected using option
-\e --log-level. In \e --quiet mode only fatal errors are reported. In such
-very severe error events, the application will usually terminate. For more
-details on the different logging levels, see documentation of module "oflog".
-
-In case the logging output should be written to file (optionally with logfile
-rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
-can be used. This configuration file also allows for directing only certain
-messages to a particular output stream and for filtering certain messages
-based on the module or application where they are generated. An example
-configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
-
-\section dcm2pdf_exit_codes EXIT CODES
-
-The \b dcm2pdf utility uses the following exit codes when terminating. This
-enables the user to check for the reason why the application terminated.
-
-\subsection dcm2cda_exit_codes_general general
-\verbatim
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-\endverbatim
-
-\subsection dcm2cda_exit_codes_input_file_errors input file errors
-\verbatim
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-\endverbatim
-
-\subsection dcm2cda_exit_codes_output_file_errors output file errors
-\verbatim
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-\endverbatim
-
-\subsection dcm2cda_exit_codes_processing_errors processing errors
-\verbatim
-EXITCODE_CANNOT_CONVERT_TO_UNICODE 80
-EXITCODE_CANNOT_WRITE_VALID_JSON 81
-\endverbatim
-
-\section dcm2pdf_command_line COMMAND LINE
-
-All command line tools use the following notation for parameters: square
-brackets enclose optional values (0-1), three trailing dots indicate that
-multiple values are allowed (1-n), a combination of both means 0 to n values.
-
-Command line options are distinguished from parameters by a leading '+' or '-'
-sign, respectively. Usually, order and position of command line options are
-arbitrary (i.e. they can appear anywhere). However, if options are mutually
-exclusive the rightmost appearance is used. This behavior conforms to the
-standard evaluation rules of common Unix shells.
-
-In addition, one or more command files can be specified using an '@' sign as a
-prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
-is replaced by the content of the corresponding text file (multiple
-whitespaces are treated as a single separator unless they appear between two
-quotation marks) prior to any further evaluation. Please note that a command
-file cannot contain another command file. This simple but effective approach
-allows one to summarize common combinations of options/parameters and avoids
-longish and confusing command lines (an example is provided in file
-<em>\<datadir\>/dumppat.txt</em>).
-
-\section dcm2pdf_environment ENVIRONMENT
-
-The \b dcm2pdf utility will attempt to load DICOM data dictionaries specified
-in the \e DCMDICTPATH environment variable. By default, i.e. if the
-\e DCMDICTPATH environment variable is not set, the file
-<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
-into the application (default for Windows).
-
-The default behavior should be preferred and the \e DCMDICTPATH environment
-variable only used when alternative data dictionaries are required. The
-\e DCMDICTPATH environment variable has the same format as the Unix shell
-\e PATH variable in that a colon (":") separates entries. On Windows systems,
-a semicolon (";") is used as a separator. The data dictionary code will
-attempt to load each file specified in the \e DCMDICTPATH environment variable.
-It is an error if no data dictionary can be loaded.
+The \b dcm2pdf tool is deprecated. Use \b dcmdecap instead, which supports
+the same command line parameters, and more.
\section dcm2pdf_see_also SEE ALSO
-<b>pdf2dcm</b>(1)
+<b>dcmdecap</b>(1)
\section dcm2pdf_copyright COPYRIGHT
-Copyright (C) 2007-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2007-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcm2xml_copyright COPYRIGHT
-Copyright (C) 2002-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2002-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmconv_copyright COPYRIGHT
-Copyright (C) 1994-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1994-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmcrle_copyright COPYRIGHT
-Copyright (C) 2002-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2002-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\li \ref dcm2xml
\li \ref dcmconv
\li \ref dcmcrle
+\li \ref dcmdecap
\li \ref dcmdrle
\li \ref dcmdump
+\li \ref dcmencap
\li \ref dcmftest
\li \ref dcmgpdir
\li \ref dcmodify
\li \ref dump2dcm
\li \ref img2dcm
+\li \ref json2dcm
\li \ref pdf2dcm
\li \ref stl2dcm
\li \ref xml2dcm
--- /dev/null
+/*!
+
+\if MANPAGES
+\page dcmdecap Extract encapsulated file from DICOM encapsulated storage object
+\else
+\page dcmdecap dcmdecap: Extract encapsulated file from DICOM encapsulated storage object
+\endif
+
+\section dcmdecap_synopsis SYNOPSIS
+
+\verbatim
+dcmdecap [options] dcmfile-in encfile-out
+\endverbatim
+
+\section dcmdecap_description DESCRIPTION
+
+The \b dcmdecap utility reads a DICOM file of one of the Encapsulated Storage SOP
+Classes (\e dcmfile-in), extracts the embedded document and writes it to an
+output file (\e encfile-out). Optionally a command can be executed after the
+creation of the output file.
+
+\section dcmdecap_parameters PARAMETERS
+
+\verbatim
+dcmfile-in DICOM input filename ("-" for stdin)
+
+encfile-out Encapsulated document output filename ("-" for stdout)
+\endverbatim
+
+\section dcmdecap_options OPTIONS
+
+\subsection dcmdecap_general_options general options
+\verbatim
+ -h --help
+ print this help text and exit
+
+ --version
+ print version information and exit
+
+ --arguments
+ print expanded command line arguments
+
+ -q --quiet
+ quiet mode, print no warnings and errors
+
+ -v --verbose
+ verbose mode, print processing details
+
+ -d --debug
+ debug mode, print debug information
+
+ -ll --log-level [l]evel: string constant
+ (fatal, error, warn, info, debug, trace)
+ use level l for the logger
+
+ -lc --log-config [f]ilename: string
+ use config file f for the logger
+\endverbatim
+
+\subsection dcmdecap_input_options input options
+\verbatim
+input file format:
+
+ +f --read-file
+ read file format or data set (default)
+
+ +fo --read-file-only
+ read file format only
+
+ -f --read-dataset
+ read data set without file meta information
+
+input transfer syntax:
+
+ -t= --read-xfer-auto
+ use TS recognition (default)
+
+ -td --read-xfer-detect
+ ignore TS specified in the file meta header
+
+ -te --read-xfer-little
+ read with explicit VR little endian TS
+
+ -tb --read-xfer-big
+ read with explicit VR big endian TS
+
+ -ti --read-xfer-implicit
+ read with implicit VR little endian TS
+
+parsing of odd-length attributes:
+
+ +ao --accept-odd-length
+ accept odd length attributes (default)
+
+ +ae --assume-even-length
+ assume real length is one byte larger
+
+handling of undefined length UN elements:
+
+ +ui --enable-cp246
+ read undefined len UN as implicit VR (default)
+
+ -ui --disable-cp246
+ read undefined len UN as explicit VR
+
+handling of defined length UN elements:
+
+ -uc --retain-un
+ retain elements as UN (default)
+
+ +uc --convert-un
+ convert to real VR if known
+
+automatic data correction:
+
+ +dc --enable-correction
+ enable automatic data correction (default)
+
+ -dc --disable-correction
+ disable automatic data correction
+
+bitstream format of deflated input:
+
+ +bd --bitstream-deflated
+ expect deflated bitstream (default)
+
+ +bz --bitstream-zlib
+ expect deflated zlib bitstream
+\endverbatim
+
+\subsection dcmdecap_processing_options processing options
+execution options:
+\verbatim
+ -x --exec [c]ommand: string
+ execute command c after document extraction
+\endverbatim
+
+\section dcmdecap_notes NOTES
+
+Option \e --exec allows for the execution of a certain command line after the
+creation of the PDF document. The command line to be executed is passed to
+this option as a parameter. The specified command line may contain the
+placeholder '\#f', which will be replaced by the output filename at run time.
+The specified command line is executed in the foreground, i.e. \b dcmdecap will
+be blocked until the command terminates.
+
+\section dcmdecap_logging LOGGING
+
+The level of logging output of the various command line tools and underlying
+libraries can be specified by the user. By default, only errors and warnings
+are written to the standard error stream. Using option \e --verbose also
+informational messages like processing details are reported. Option
+\e --debug can be used to get more details on the internal activity, e.g. for
+debugging purposes. Other logging levels can be selected using option
+\e --log-level. In \e --quiet mode only fatal errors are reported. In such
+very severe error events, the application will usually terminate. For more
+details on the different logging levels, see documentation of module "oflog".
+
+In case the logging output should be written to file (optionally with logfile
+rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
+can be used. This configuration file also allows for directing only certain
+messages to a particular output stream and for filtering certain messages
+based on the module or application where they are generated. An example
+configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
+
+\section dcmdecap_exit_codes EXIT CODES
+
+The \b dcmdecap utility uses the following exit codes when terminating. This
+enables the user to check for the reason why the application terminated.
+
+\subsection dcmdecap_exit_codes_general general
+\verbatim
+EXITCODE_NO_ERROR 0
+EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
+\endverbatim
+
+\subsection dcmdecap_exit_codes_input_file_errors input file errors
+\verbatim
+EXITCODE_CANNOT_READ_INPUT_FILE 20
+EXITCODE_NO_INPUT_FILES 21
+EXITCODE_INVALID_INPUT_FILE 22
+\endverbatim
+
+\subsection dcmdecap_exit_codes_output_file_errors output file errors
+\verbatim
+EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
+\endverbatim
+
+\subsection dcmdecap_exit_codes_processing_errors processing errors
+\verbatim
+EXITCODE_EXEC_FAILED 91
+\endverbatim
+
+\section dcmdecap_command_line COMMAND LINE
+
+All command line tools use the following notation for parameters: square
+brackets enclose optional values (0-1), three trailing dots indicate that
+multiple values are allowed (1-n), a combination of both means 0 to n values.
+
+Command line options are distinguished from parameters by a leading '+' or '-'
+sign, respectively. Usually, order and position of command line options are
+arbitrary (i.e. they can appear anywhere). However, if options are mutually
+exclusive the rightmost appearance is used. This behavior conforms to the
+standard evaluation rules of common Unix shells.
+
+In addition, one or more command files can be specified using an '@' sign as a
+prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
+is replaced by the content of the corresponding text file (multiple
+whitespaces are treated as a single separator unless they appear between two
+quotation marks) prior to any further evaluation. Please note that a command
+file cannot contain another command file. This simple but effective approach
+allows one to summarize common combinations of options/parameters and avoids
+longish and confusing command lines (an example is provided in file
+<em>\<datadir\>/dumppat.txt</em>).
+
+\section dcmdecap_environment ENVIRONMENT
+
+The \b dcmdecap utility will attempt to load DICOM data dictionaries specified
+in the \e DCMDICTPATH environment variable. By default, i.e. if the
+\e DCMDICTPATH environment variable is not set, the file
+<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
+into the application (default for Windows).
+
+The default behavior should be preferred and the \e DCMDICTPATH environment
+variable only used when alternative data dictionaries are required. The
+\e DCMDICTPATH environment variable has the same format as the Unix shell
+\e PATH variable in that a colon (":") separates entries. On Windows systems,
+a semicolon (";") is used as a separator. The data dictionary code will
+attempt to load each file specified in the \e DCMDICTPATH environment variable.
+It is an error if no data dictionary can be loaded.
+
+\section dcmdecap_see_also SEE ALSO
+
+<b>dcmencap</b>(1)
+
+\section dcmdecap_copyright COPYRIGHT
+
+Copyright (C) 2007-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+
+*/
\section dcmdrle_copyright COPYRIGHT
-Copyright (C) 2002-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany
+Copyright (C) 2002-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany
*/
\section dcmdump_copyright COPYRIGHT
-Copyright (C) 1994-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1994-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
--- /dev/null
+/*!
+
+\if MANPAGES
+\page dcmencap Encapsulate document into DICOM format
+\else
+\page dcmencap dcmencap: Encapsulate document into DICOM format
+\endif
+
+\section dcmencap_synopsis SYNOPSIS
+
+\verbatim
+dcmencap [options] docfile-in dcmfile-out
+\endverbatim
+
+\section dcmencap_description DESCRIPTION
+
+The \b dcmencap utility reads a document file in one of the supported file formats,
+converts it to a SOP instance of the corresponding DICOM Encapsulated Storage SOP Class
+and stores the converted data in an output file (\e dcmfile-out).
+
+\section dcmencap_parameters PARAMETERS
+
+\verbatim
+docfile-in input filename to be converted
+
+dcmfile-out DICOM output filename ("-" for stdout)
+\endverbatim
+
+\section dcmencap_options OPTIONS
+
+\subsection dcmencap_general_options general options
+\verbatim
+ -h --help
+ print this help text and exit
+
+ --version
+ print version information and exit
+
+ --arguments
+ print expanded command line arguments
+
+ -q --quiet
+ quiet mode, print no warnings and errors
+
+ -v --verbose
+ verbose mode, print processing details
+
+ -d --debug
+ debug mode, print debug information
+
+ -ll --log-level [l]evel: string constant
+ (fatal, error, warn, info, debug, trace)
+ use level l for the logger
+
+ -lc --log-config [f]ilename: string
+ use config file f for the logger
+\endverbatim
+
+\subsection dcmencap_input_options input options
+\verbatim
+input file format:
+
+ +fa --filetype-auto
+ automatically determine file type (default)
+
+ +fp --filetype-pdf
+ expect PDF file
+
+ +fc --filetype-cda
+ expect CDA file
+
+ +fs --filetype-stl
+ expect STL file
+
+ +fm --filetype-mtl
+ expect MTL file
+
+ +fo --filetype-obj
+ expect OBJ file
+\endverbatim
+
+\subsection dcmencap_dicom_document_options DICOM document options
+\verbatim
+document title:
+
+ +t --title [t]itle: string (default: empty)
+ document title
+
+ +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
+ coded representation of document title defined by coding
+ scheme designator CSD, code value CV and code meaning CM
+
+patient data:
+
+ +pn --patient-name [n]ame: string
+ patient's name in DICOM PN syntax
+
+ +pi --patient-id [i]d: string
+ patient identifier
+
+ +pb --patient-birthdate [d]ate: string (YYYYMMDD)
+ patient's birth date
+
+ +ps --patient-sex [s]ex: string (M, F or O)
+ patient's sex
+
+device data:
+
+ +mn --manufacturer [n]ame: string
+ manufacturer's name
+
+ +mm --manufacturer-model [n]ame: string
+ manufacturer's model name
+
+ +ds --device-serial [n]umber: string
+ device serial number
+
+ +sv --software-versions [v]ersions: string
+ software versions
+
+manufacturing 3d model data (STL/MTL/OBJ only):
+
+ +mu --measurement-units [CSD] [CV] [CM]: string
+ measurement units with coding scheme designator CSD,
+ code value CV and code meaning CM (default: UCUM, um, um)
+
+study and series:
+
+ +sg --generate
+ generate new study and series UIDs (default)
+
+ +st --study-from [f]ilename: string
+ read patient/study data from DICOM file
+
+ +se --series-from [f]ilename: string
+ read patient/study/series data from DICOM file
+
+instance number:
+
+ +i1 --instance-one
+ use instance number 1 (default, not with +se)
+
+ +ii --instance-inc
+ increment instance number (only with +se)
+
+ +is --instance-set [i]nstance number: integer
+ use instance number i
+
+burned-in annotation:
+
+ +an --annotation-yes
+ document contains patient identifying data (default)
+
+ -an --annotation-no
+ document does not contain patient identifying data
+\endverbatim
+
+\subsection dcmencap_processing_options processing options
+\verbatim
+CDA processing options:
+
+ -ov --no-override
+ CDA patient and document data must match study,
+ series or manually entered information (default)
+
+ +ov --override
+ CDA's data will be overwritten by study, series
+ or manually entered information
+
+other processing options:
+
+ -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
+ add further attribute
+\endverbatim
+
+\subsection dcmencap_output_options output options
+\verbatim
+output transfer syntax:
+ +te --write-xfer-little
+ write with explicit VR little endian (default)
+
+ +tb --write-xfer-big
+ write with explicit VR big endian TS
+
+ +ti --write-xfer-implicit
+ write with implicit VR little endian TS
+
+group length encoding:
+
+ -g --group-length-remove
+ write without group length elements (default)
+
+ +g --group-length-create
+ write with group length elements
+
+length encoding in sequences and items:
+
+ +e --length-explicit
+ write with explicit lengths (default)
+
+ -e --length-undefined
+ write with undefined lengths
+
+data set trailing padding (not with --write-dataset):
+
+ -p --padding-off
+ no padding (implicit if --write-dataset)
+
+ +p --padding-create [f]ile-pad [i]tem-pad: integer
+ align file on multiple of f bytes
+ and items on multiple of i bytes
+\endverbatim
+
+\section dcmencap_notes NOTES
+
+\subsection dcmencap_attribute_sources Attribute Sources
+
+The application may be fed with some additional input for filling mandatory
+(and optional) attributes in the new DICOM file like patient, study and series
+information:
+
+- The \e --key option can be used to add further attributes to the DICOM output
+ file.
+
+- It is also possible to specify sequences, items and nested attributes using
+ the \e --key option. In these cases, a special "path" notation has to be
+ used. Details on this path notation can be found in the documentation of
+ \b dcmodify.
+
+- The \e --key option can be present more than once.
+
+- The value part (after the '=') may be absent causing the attribute to be set
+ with zero length.
+
+- Please be advised that the \e --key option is applied at the very end, just
+ before saving the DICOM file, so there is no value checking whatsoever.
+
+\section dcmencap_logging LOGGING
+
+The level of logging output of the various command line tools and underlying
+libraries can be specified by the user. By default, only errors and warnings
+are written to the standard error stream. Using option \e --verbose also
+informational messages like processing details are reported. Option
+\e --debug can be used to get more details on the internal activity, e.g. for
+debugging purposes. Other logging levels can be selected using option
+\e --log-level. In \e --quiet mode only fatal errors are reported. In such
+very severe error events, the application will usually terminate. For more
+details on the different logging levels, see documentation of module "oflog".
+
+In case the logging output should be written to file (optionally with logfile
+rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
+can be used. This configuration file also allows for directing only certain
+messages to a particular output stream and for filtering certain messages
+based on the module or application where they are generated. An example
+configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
+
+\section dcmencap_command_line COMMAND LINE
+
+All command line tools use the following notation for parameters: square
+brackets enclose optional values (0-1), three trailing dots indicate that
+multiple values are allowed (1-n), a combination of both means 0 to n values.
+
+Command line options are distinguished from parameters by a leading '+' or '-'
+sign, respectively. Usually, order and position of command line options are
+arbitrary (i.e. they can appear anywhere). However, if options are mutually
+exclusive the rightmost appearance is used. This behavior conforms to the
+standard evaluation rules of common Unix shells.
+
+In addition, one or more command files can be specified using an '@' sign as a
+prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
+is replaced by the content of the corresponding text file (multiple
+whitespaces are treated as a single separator unless they appear between two
+quotation marks) prior to any further evaluation. Please note that a command
+file cannot contain another command file. This simple but effective approach
+allows one to summarize common combinations of options/parameters and avoids
+longish and confusing command lines (an example is provided in file
+<em>\<datadir\>/dumppat.txt</em>).
+
+\section dcmencap_exit_codes EXIT CODES
+
+The \b dcmencap utility uses the following exit codes when terminating. This
+enables the user to check for the reason why the application terminated.
+
+\subsection dcmencap_exit_codes_general general
+\verbatim
+EXITCODE_NO_ERROR 0
+\endverbatim
+
+\subsection dcmencap_exit_codes_input_file_errors input file errors
+\verbatim
+EXITCODE_INVALID_INPUT_FILE 22
+\endverbatim
+
+\subsection dcmencap_exit_codes_output_file_errors output file errors
+\verbatim
+EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
+\endverbatim
+
+\section dcmencap_environment ENVIRONMENT
+
+The \b dcmencap utility will attempt to load DICOM data dictionaries specified
+in the \e DCMDICTPATH environment variable. By default, i.e. if the
+\e DCMDICTPATH environment variable is not set, the file
+<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
+into the application (default for Windows).
+
+The default behavior should be preferred and the \e DCMDICTPATH environment
+variable only used when alternative data dictionaries are required. The
+\e DCMDICTPATH environment variable has the same format as the Unix shell
+\e PATH variable in that a colon (":") separates entries. On Windows systems,
+a semicolon (";") is used as a separator. The data dictionary code will
+attempt to load each file specified in the \e DCMDICTPATH environment
+variable.
+It is an error if no data dictionary can be loaded.
+
+\section dcmencap_copyright COPYRIGHT
+
+Copyright (C) 2018-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+
+*/
\section dcmftest_copyright COPYRIGHT
-Copyright (C) 1997-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1997-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmgpdir_copyright COPYRIGHT
-Copyright (C) 1996-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1996-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmodify_copyright COPYRIGHT
-Copyright (C) 2003-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2003-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dump2dcm_copyright COPYRIGHT
-Copyright (C) 1996-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1996-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
information, aka 'mrfx') inside the DICOM stream, the option \e --keep-appn
does the trick. Pay attention that the plugin will check the actual color
transform specified in the APP8/HP marker. Since DICOM does not allow any
-color transform to be specified in the APP8 marker, only a value of `0` (no
+color transform to be specified in the APP8 marker, only a value of 0 (no
color transform) is accepted.
\subsubsection img2dcm_bmp_input_plugin BMP Input Plugin
\section img2dcm_copyright COPYRIGHT
-Copyright (C) 2007-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2007-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
--- /dev/null
+/*!
+
+\if MANPAGES
+\page json2dcm Convert JSON document to DICOM file or data set
+\else
+\page json2dcm json2dcm: Convert JSON document to DICOM file or data set
+\endif
+
+\section json2dcm_synopsis SYNOPSIS
+
+\verbatim
+json2dcm [options] jsonfile-in dcmfile-out
+\endverbatim
+
+\section json2dcm_description DESCRIPTION
+
+The \b json2dcm utility converts the contents of a JSON (JavaScript Object
+Notation) document to a binary DICOM file or data set. The JSON document is
+expected to conform to the "DICOM JSON Model" as defined in DICOM Part 18
+Section F. Such JSON files can be created, e.g., using the \b dcm2json tool.
+
+\section json2dcm_parameters PARAMETERS
+
+\verbatim
+jsonfile-in JSON input filename to be converted ("-" for stdin)
+
+dcmfile-out DICOM output filename ("-" for stdout)
+\endverbatim
+
+\section json2dcm_options OPTIONS
+
+\subsection json2dcm_general_options general options
+\verbatim
+ -h --help
+ print this help text and exit
+
+ --version
+ print version information and exit
+
+ --arguments
+ print expanded command line arguments
+
+ -q --quiet
+ quiet mode, print no warnings and errors
+
+ -v --verbose
+ verbose mode, print processing details
+
+ -d --debug
+ debug mode, print debug information
+
+ -ll --log-level [l]evel: string constant
+ (fatal, error, warn, info, debug, trace)
+ use level l for the logger
+
+ -lc --log-config [f]ilename: string
+ use config file f for the logger
+\endverbatim
+
+\subsection json2dcm_input_options input options
+\verbatim
+input file format:
+
+ +f --read-meta-info
+ read meta information if present (default)
+
+ -f --ignore-meta-info
+ ignore file meta information
+\endverbatim
+
+\subsection json2dcm_processing_options processing options
+\verbatim
+unique identifiers:
+
+ +Ug --generate-new-uids
+ generate new Study/Series/SOP Instance UID
+
+ -Uo --dont-overwrite-uids
+ do not overwrite existing UIDs (default)
+
+ +Uo --overwrite-uids
+ overwrite existing UIDs
+
+bulkdata URI handling:
+
+ +Bu --parse-bulkdata-uri
+ parse Bulkdata URIs (default)
+
+ -Bu --ignore-bulkdata-uri
+ ignore Bulkdata URIs
+
+ +Bd --add-bulkdata-dir [d]irectory: string
+ add d to list of permitted bulk data sources
+
+handling of arrays with multiple data sets:
+
+ -ar --array-reject
+ reject multiple data sets (default)
+
+ +as --array-select [n]umber: integer
+ select data set n from array
+
+ +ar --array-sequence
+ store all data sets in private sequence
+\endverbatim
+
+\subsection json2dcm_output_options output options
+\verbatim
+output file format:
+
+ +F --write-file
+ write file format (default)
+
+ -F --write-dataset
+ write data set without file meta information
+
+ +Fu --update-meta-info
+ update particular file meta information
+
+output transfer syntax:
+
+ +t= --write-xfer-same
+ write with same TS as input (default)
+
+ +te --write-xfer-little
+ write with explicit VR little endian TS
+
+ +tb --write-xfer-big
+ write with explicit VR big endian TS
+
+ +ti --write-xfer-implicit
+ write with implicit VR little endian TS
+
+ +td --write-xfer-deflated
+ write with deflated explicit VR little endian TS
+
+error handling:
+
+ -E --stop-on-error
+ do not write if document is invalid (default)
+
+ +E --ignore-errors
+ attempt to write even if document is invalid
+
+post-1993 value representations:
+
+ +u --enable-new-vr
+ enable support for new VRs (UN/UT) (default)
+
+ -u --disable-new-vr
+ disable support for new VRs, convert to OB
+
+length encoding in sequences and items:
+
+ +e --length-explicit
+ write with explicit lengths (default)
+
+ -e --length-undefined
+ write with undefined lengths
+
+charset handling:
+
+ +c --charset-accept
+ write with the given charset in JSON (default)
+
+ -c --charset-replace
+ replace the given charset in JSON with UTF-8
+
+deflate compression level (only with --write-xfer-deflated):
+
+ +cl --compression-level [l]evel: integer (default: 6)
+ 0=uncompressed, 1=fastest, 9=best compression
+\endverbatim
+
+\section json2dcm_notes NOTES
+
+The basic structure of the JSON input expected looks like the following (see
+DICOM Part 18 Section F for details):
+
+\verbatim
+{
+ "00080005": {
+ "vr": "CS",
+ "Value": [
+ "ISO_IR 192"
+ ]
+ },
+ "00080020": {
+ "vr": "DT",
+ "Value": [
+ "20130409"
+ ]
+ },
+ "00080030": {
+ "vr": "TM",
+ "Value": [
+ "131600.0000"
+ ]
+ },
+ "00080050": {
+ "vr": "SH",
+ "Value": [
+ "11235813"
+ ]
+ },
+ "00080056": {
+ "vr": "CS",
+ "Value": [
+ "ONLINE"
+ ]
+ },
+ "00080061": {
+ "vr": "CS",
+ "Value": [
+ "CT",
+ "PET"
+ ]
+ },
+ "00080090": {
+ "vr": "PN",
+ "Value": [
+ {
+ "Alphabetic": "^Bob^^Dr."
+ }
+ ]
+ },
+ "00081190": {
+ "vr": "UR",
+ "Value": [
+ "http://wado.nema.org/studies/
+ 1.2.392.200036.9116.2.2.2.1762893313.1029997326.945873"
+ ]
+ },
+ "00090010": {
+ "vr": "LO",
+ "Value": [
+ "Vendor A"
+ ]
+ },
+ "00091002": {
+ "vr": "UN",
+ "InlineBinary": "z0x9c8v7"
+ },
+ "00100010": {
+ "vr": "PN",
+ "Value": [
+ {
+ "Alphabetic": "Wang^XiaoDong"
+ }
+ ]
+ },
+ "00100020": {
+ "vr": "LO",
+ "Value": [
+ "12345"
+ ]
+ },
+ "00100021": {
+ "vr": "LO",
+ "Value": [
+ "Hospital A"
+ ]
+ },
+ "00100030": {
+ "vr": "DA",
+ "Value": [
+ "19670701"
+ ]
+ },
+ "00100040": {
+ "vr": "CS",
+ "Value": [
+ "M"
+ ]
+ },
+ "00101002": {
+ "vr": "SQ",
+ "Value": [
+ {
+ "00100020": {
+ "vr": "LO",
+ "Value": [
+ "54321"
+ ]
+ },
+ "00100021": {
+ "vr": "LO",
+ "Value": [
+ "Hospital B"
+ ]
+ }
+ },
+ {
+ "00100020": {
+ "vr": "LO",
+ "Value": [
+ "24680"
+ ]
+ },
+ "00100021": {
+ "vr": "LO",
+ "Value": [
+ "Hospital C"
+ ]
+ }
+ }
+ ]
+ },
+ "0020000D": {
+ "vr": "UI",
+ "Value": [
+ "1.2.392.200036.9116.2.2.2.1762893313.1029997326.945873"
+ ]
+ },
+ "00200010": {
+ "vr": "SH",
+ "Value": [
+ "11235813"
+ ]
+ },
+ "00201206": {
+ "vr": "IS",
+ "Value": [
+ 4
+ ]
+ },
+ "00201208": {
+ "vr": "IS",
+ "Value": [
+ 942
+ ]
+ }
+}
+\endverbatim
+
+\subsection json2dcm_character_encoding Character Encoding
+
+The JSON format only supports UTF-8 encoding. Thus the generated DICOM file
+will also contain UTF-8 encoding. If the JSON file does not contain a specific
+character set, or a specific character set other than "ISO_IR 192", a warning
+will be issued.
+
+\subsection json2dcm_bulk_data Binary Data, Bulk Data, and Pixel Data
+
+The DICOM JSON Model uses "InlineBinary" to store attribute values of binary
+value representations such as "OB", "OW", "OD", "OF", "OL", "OV" etc.
+in Base64 encoded form. This is supported in \b json2dcm for all binary
+attributes, including unencapsulated pixel data.
+
+The DICOM JSON Model also permits attribute values to be stored separately
+from the JSON data set and to be referenced through a BulkDataURI.
+This is supported for file URIs that reference files in the local filesystem.
+\b json2dcm tool also supports the inofficial extension to the file URI
+scheme generated by \e DCM4CHE, where parameters named "offset" and "length"
+are appended to the file URI in order to refer to a specific part of a file.
+HTTP URIs as well as URIs that identify another part in a MIME
+multipart/related structure are not yet supported in \b json2dcm.
+If the command line option \e --ignore-bulkdata-uri is specified,
+then all bulk data URIs are ignored and attributes with bulk data
+will be written with empty value.
+
+Finally, encapsulated (in particular, compressed) pixel data is not supported
+by \b json2dcm because the syntax of the DICOM JSON Model for this specific
+case is not defined in the DICOM standard yet.
+
+\subsection json2dcm_arrays Arrays of Data Sets
+
+The DICOM JSON Model uses a JSON array structure to return multiple data sets
+in DICOMweb services such as WADO-RS or QIDO-RS. JSON arrays containing a
+single DICOM data set are automatically recognized by \b json2dcm and treated
+like a data set without the surrounding array structure. JSON arrays
+containing multiple data sets are rejected by default. Alternatively, the
+\e --array-select option can be used to select one data set from the array to
+be converted. The \e --array-sequence option causes all data sets to be
+written as sequence items into a single private sequence with attribute tag
+(0009,1000). Such files, which are mostly intended for debugging purposes, can
+be recognized by the private creator element (0009,0010), which has the value
+"JSON2DCM_LIST_OF_DATASETS".
+
+\subsection json2dcm_trailing_commas Trailing Commas
+
+Trailing commas are not permitted in JSON, but \b json2dcm will still accept
+such JSON data sets without warning or error message because they are handled
+gracefully by the underlying JSON parser. Users should, therefore, not assume
+that a JSON data set is valid just because \b json2dcm accepts it. This tool
+is not designed as a validator for JSON or the DICOM JSON Model.
+
+\section json2dcm_logging LOGGING
+
+The level of logging output of the various command line tools and underlying
+libraries can be specified by the user. By default, only errors and warnings
+are written to the standard error stream. Using option \e --verbose also
+informational messages like processing details are reported. Option
+\e --debug can be used to get more details on the internal activity, e.g. for
+debugging purposes. Other logging levels can be selected using option
+\e --log-level. In \e --quiet mode only fatal errors are reported. In such
+very severe error events, the application will usually terminate. For more
+details on the different logging levels, see documentation of module "oflog".
+
+In case the logging output should be written to file (optionally with logfile
+rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
+can be used. This configuration file also allows for directing only certain
+messages to a particular output stream and for filtering certain messages
+based on the module or application where they are generated. An example
+configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
+
+\section json2dcm_command_line COMMAND LINE
+
+All command line tools use the following notation for parameters: square
+brackets enclose optional values (0-1), three trailing dots indicate that
+multiple values are allowed (1-n), a combination of both means 0 to n values.
+
+Command line options are distinguished from parameters by a leading '+' or '-'
+sign, respectively. Usually, order and position of command line options are
+arbitrary (i.e. they can appear anywhere). However, if options are mutually
+exclusive the rightmost appearance is used. This behavior conforms to the
+standard evaluation rules of common Unix shells.
+
+In addition, one or more command files can be specified using an '@' sign as a
+prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
+is replaced by the content of the corresponding text file (multiple
+whitespaces are treated as a single separator unless they appear between two
+quotation marks) prior to any further evaluation. Please note that a command
+file cannot contain another command file. This simple but effective approach
+allows one to summarize common combinations of options/parameters and avoids
+longish and confusing command lines (an example is provided in file
+<em>\<datadir\>/dumppat.txt</em>).
+
+\section json2dcm_exit_codes EXIT CODES
+
+The \b dcm2json utility uses the following exit codes when terminating. This
+enables the user to check for the reason why the application terminated.
+
+\subsection json2dcm_exit_codes_general general
+\verbatim
+EXITCODE_NO_ERROR 0
+EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
+\endverbatim
+
+\subsection json2dcm_exit_codes_input_file_errors input file errors
+\verbatim
+EXITCODE_CANNOT_READ_INPUT_FILE 20
+\endverbatim
+
+\subsection json2dcm_exit_codes_output_file_errors output file errors
+\verbatim
+EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
+\endverbatim
+
+\subsection json2dcm_exit_codes_processing_errors processing errors
+\verbatim
+EXITCODE_INVALID_JSON_CONTENT 65
+EXITCODE_BULKDATA_URI_NOT_SUPPORTED 66
+\endverbatim
+
+\section json2dcm_environment ENVIRONMENT
+
+The \b json2dcm utility will attempt to load DICOM data dictionaries specified
+in the \e DCMDICTPATH environment variable. By default, i.e. if the
+\e DCMDICTPATH environment variable is not set, the file
+<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
+into the application (default for Windows).
+
+The default behavior should be preferred and the \e DCMDICTPATH environment
+variable only used when alternative data dictionaries are required. The
+\e DCMDICTPATH environment variable has the same format as the Unix shell
+\e PATH variable in that a colon (":") separates entries. On Windows systems,
+a semicolon (";") is used as a separator. The data dictionary code will
+attempt to load each file specified in the \e DCMDICTPATH environment variable.
+It is an error if no data dictionary can be loaded.
+
+\section json2dcm_see_also SEE ALSO
+
+<b>dcm2json</b>(1)
+<b>dump2dcm</b>(2)
+
+\section json2dcm_copyright COPYRIGHT
+
+Copyright (C) 2024-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+
+*/
\section pdf2dcm_description DESCRIPTION
-The \b pdf2dcm utility reads a PDF file (\e pdffile-in), converts it to a
-DICOM Encapsulated PDF Storage SOP instance and stores the converted data
-to an output file (\e dcmfile-out).
-
-\section pdf2dcm_parameters PARAMETERS
-
-\verbatim
-pdffile-in PDF input filename to be encapsulated
-
-dcmfile-out DICOM output filename ("-" for stdout)
-\endverbatim
-
-\section pdf2dcm_options OPTIONS
-
-\subsection pdf2dcm_general_options general options
-\verbatim
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-\endverbatim
-
-\subsection pdf2dcm_dicom_document_options DICOM document options
-\verbatim
-document title:
-
- +t --title [t]itle: string (default: empty)
- document title
-
- +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
- coded representation of document title defined by coding
- scheme designator CSD, code value CV and code meaning CM
-
-patient data:
-
- +pn --patient-name [n]ame: string
- patient's name in DICOM PN syntax
-
- +pi --patient-id [i]d: string
- patient identifier
-
- +pb --patient-birthdate [d]ate: string (YYYYMMDD)
- patient's birth date
-
- +ps --patient-sex [s]ex: string (M, F or O)
- patient's sex
-
-study and series:
-
- +sg --generate
- generate new study and series UIDs (default)
-
- +st --study-from [f]ilename: string
- read patient/study data from DICOM file
-
- +se --series-from [f]ilename: string
- read patient/study/series data from DICOM file
-
-instance number:
-
- +i1 --instance-one
- use instance number 1 (default, not with +se)
-
- +ii --instance-inc
- increment instance number (only with +se)
-
- +is --instance-set [i]nstance number: integer
- use instance number i
-
-burned-in annotation:
-
- +an --annotation-yes
- document contains patient identifying data (default)
-
- -an --annotation-no
- document does not contain patient identifying data
-\endverbatim
-
-\subsection pdf2dcm_processing_options processing options
-\verbatim
-other processing options:
-
- -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
- add further attribute
-\endverbatim
-
-\subsection pdf2dcm_output_options output options
-\verbatim
-output file format:
-
- +F --write-file
- write file format (default)
-
- -F --write-dataset
- write data set without file meta information
-
-group length encoding:
-
- +g= --group-length-recalc
- recalculate group lengths if present (default)
-
- +g --group-length-create
- always write with group length elements
-
- -g --group-length-remove
- always write without group length elements
-
-length encoding in sequences and items:
-
- +e --length-explicit
- write with explicit lengths (default)
-
- -e --length-undefined
- write with undefined lengths
-
-data set trailing padding (not with --write-dataset):
-
- -p --padding-off
- no padding (implicit if --write-dataset)
-
- +p --padding-create [f]ile-pad [i]tem-pad: integer
- align file on multiple of f bytes
- and items on multiple of i bytes
-\endverbatim
-
-\section pdf2dcm_notes NOTES
-
-\subsection pdf2dcm_attribute_sources Attribute Sources
-
-The application may be fed with some additional input for filling mandatory
-(and optional) attributes in the new DICOM file like patient, study and series
-information:
-
-- The \e --key option can be used to add further attributes to the DICOM output
- file.
-
-- It is also possible to specify sequences, items and nested attributes using
- the \e --key option. In these cases, a special "path" notation has to be
- used. Details on this path notation can be found in the documentation of
- \b dcmodify.
-
-- The \e --key option can be present more than once.
-
-- The value part (after the '=') may be absent causing the attribute to be set
- with zero length.
-
-- Please be advised that the \e --key option is applied at the very end, just
- before saving the DICOM file, so there is no value checking whatsoever.
-
-\section pdf2dcm_logging LOGGING
-
-The level of logging output of the various command line tools and underlying
-libraries can be specified by the user. By default, only errors and warnings
-are written to the standard error stream. Using option \e --verbose also
-informational messages like processing details are reported. Option
-\e --debug can be used to get more details on the internal activity, e.g. for
-debugging purposes. Other logging levels can be selected using option
-\e --log-level. In \e --quiet mode only fatal errors are reported. In such
-very severe error events, the application will usually terminate. For more
-details on the different logging levels, see documentation of module "oflog".
-
-In case the logging output should be written to file (optionally with logfile
-rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
-can be used. This configuration file also allows for directing only certain
-messages to a particular output stream and for filtering certain messages
-based on the module or application where they are generated. An example
-configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
-
-\section pdf2dcm_command_line COMMAND LINE
-
-All command line tools use the following notation for parameters: square
-brackets enclose optional values (0-1), three trailing dots indicate that
-multiple values are allowed (1-n), a combination of both means 0 to n values.
-
-Command line options are distinguished from parameters by a leading '+' or '-'
-sign, respectively. Usually, order and position of command line options are
-arbitrary (i.e. they can appear anywhere). However, if options are mutually
-exclusive the rightmost appearance is used. This behavior conforms to the
-standard evaluation rules of common Unix shells.
-
-In addition, one or more command files can be specified using an '@' sign as a
-prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
-is replaced by the content of the corresponding text file (multiple
-whitespaces are treated as a single separator unless they appear between two
-quotation marks) prior to any further evaluation. Please note that a command
-file cannot contain another command file. This simple but effective approach
-allows one to summarize common combinations of options/parameters and avoids
-longish and confusing command lines (an example is provided in file
-<em>\<datadir\>/dumppat.txt</em>).
-
-\section pdf2dcm_exit_codes EXIT CODES
-
-The \b pdf2dcm utility uses the following exit codes when terminating. This
-enables the user to check for the reason why the application terminated.
-
-\subsection pdf2dcm_exit_codes_general general
-\verbatim
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-EXITCODE_MEMORY_EXHAUSTED 4
-\endverbatim
-
-\subsection pdf2dcm_exit_codes_input_file_errors input file errors
-\verbatim
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-\endverbatim
-
-\subsection pdf2dcm_exit_codes_output_file_errors output file errors
-\verbatim
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-\endverbatim
-
-\section pdf2dcm_environment ENVIRONMENT
-
-The \b pdf2dcm utility will attempt to load DICOM data dictionaries specified
-in the \e DCMDICTPATH environment variable. By default, i.e. if the
-\e DCMDICTPATH environment variable is not set, the file
-<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
-into the application (default for Windows).
-
-The default behavior should be preferred and the \e DCMDICTPATH environment
-variable only used when alternative data dictionaries are required. The
-\e DCMDICTPATH environment variable has the same format as the Unix shell
-\e PATH variable in that a colon (":") separates entries. On Windows systems,
-a semicolon (";") is used as a separator. The data dictionary code will
-attempt to load each file specified in the \e DCMDICTPATH environment
-variable.
-It is an error if no data dictionary can be loaded.
+The \b pdf2dcm tool is deprecated. Use \b dcmencap instead, which supports
+the same command line parameters, and more.
\section pdf2dcm_see_also SEE ALSO
-<b>dcm2pdf</b>(1)
+<b>dcmencap</b>(1)
\section pdf2dcm_copyright COPYRIGHT
-Copyright (C) 2005-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2005-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section stl2dcm_description DESCRIPTION
-The \b stl2dcm utility reads a STL file (\e stlfile-in), converts it to a
-DICOM Encapsulated STL Storage SOP instance and stores the converted data
-to an output file (\e dcmfile-out).
+The \b stl2dcm tool is deprecated. Use \b dcmencap instead, which supports
+the same command line parameters, and more.
-\section stl2dcm_parameters PARAMETERS
+\section stl2dcm_see_also SEE ALSO
-\verbatim
-stlfile-in STL input filename to be encapsulated
-
-dcmfile-out DICOM output filename ("-" for stdout)
-\endverbatim
-
-\section stl2dcm_options OPTIONS
-
-\subsection stl2dcm_general_options general options
-\verbatim
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-\endverbatim
-
-\subsection stl2dcm_dicom_document_options DICOM document options
-\verbatim
-document title:
-
- +t --title [t]itle: string (default: empty)
- document title
-
- +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
- coded representation of document title defined by coding
- scheme designator CSD, code value CV and code meaning CM
-
-patient data:
-
- +pn --patient-name [n]ame: string
- patient's name in DICOM PN syntax
-
- +pi --patient-id [i]d: string
- patient identifier
-
- +pb --patient-birthdate [d]ate: string (YYYYMMDD)
- patient's birth date
-
- +ps --patient-sex [s]ex: string (M, F or O)
- patient's sex
-
-study and series:
-
- +sg --generate
- generate new study and series UIDs (default)
-
- +st --study-from [f]ilename: string
- read patient/study data from DICOM file
-
- +se --series-from [f]ilename: string
- read patient/study/series data from DICOM file
-
-instance number:
-
- +i1 --instance-one
- use instance number 1 (default, not with +se)
-
- +ii --instance-inc
- increment instance number (only with +se)
-
- +is --instance-set [i]nstance number: integer
- use instance number i
-
-burned-in annotation:
-
- +an --annotation-yes
- document contains patient identifying data (default)
-
- -an --annotation-no
- document does not contain patient identifying data
-
-enhanced general equipment:
-
- +mn --manufacturer [n]ame: string
- manufacturer's name
-
- +mm --manufacturer-model [n]ame: string
- manufacturer's model name
-
- +ds --device-serial [n]umber: string
- device serial number
-
- +sv --software-versions [v]ersions: string
- software versions
-
-3d model measurement units:
-
- +mu --measurement-units [CSD] [CV] [CM]: string
- measurement units with coding scheme designator CSD,
- code value CV and code meaning CM (default: UCUM, um, um)
-\endverbatim
-
-\subsection stl2dcm_processing_options processing options
-\verbatim
-other processing options:
-
- -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
- add further attribute
-\endverbatim
-
-\subsection stl2dcm_output_options output options
-\verbatim
-output file format:
-
- +F --write-file
- write file format (default)
-
- -F --write-dataset
- write data set without file meta information
-
-group length encoding:
-
- +g= --group-length-recalc
- recalculate group lengths if present (default)
-
- +g --group-length-create
- always write with group length elements
-
- -g --group-length-remove
- always write without group length elements
-
-length encoding in sequences and items:
-
- +e --length-explicit
- write with explicit lengths (default)
-
- -e --length-undefined
- write with undefined lengths
-
-data set trailing padding (not with --write-dataset):
-
- -p --padding-off
- no padding (implicit if --write-dataset)
-
- +p --padding-create [f]ile-pad [i]tem-pad: integer
- align file on multiple of f bytes
- and items on multiple of i bytes
-\endverbatim
-
-\section stl2dcm_notes NOTES
-
-\subsection stl2dcm_attribute_sources Attribute Sources
-
-The application may be fed with some additional input for filling mandatory
-(and optional) attributes in the new DICOM file like patient, study and series
-information:
-
-- The \e --key option can be used to add further attributes to the DICOM output
- file.
-
-- It is also possible to specify sequences, items and nested attributes using
- the \e --key option. In these cases, a special "path" notation has to be
- used. Details on this path notation can be found in the documentation of
- \b dcmodify.
-
-- The \e --key option can be present more than once.
-
-- The value part (after the '=') may be absent causing the attribute to be set
- with zero length.
-
-- Please be advised that the \e --key option is applied at the very end, just
- before saving the DICOM file, so there is no value checking whatsoever.
-
-\section stl2dcm_logging LOGGING
-
-The level of logging output of the various command line tools and underlying
-libraries can be specified by the user. By default, only errors and warnings
-are written to the standard error stream. Using option \e --verbose also
-informational messages like processing details are reported. Option
-\e --debug can be used to get more details on the internal activity, e.g. for
-debugging purposes. Other logging levels can be selected using option
-\e --log-level. In \e --quiet mode only fatal errors are reported. In such
-very severe error events, the application will usually terminate. For more
-details on the different logging levels, see documentation of module "oflog".
-
-In case the logging output should be written to file (optionally with logfile
-rotation), to syslog (Unix) or the event log (Windows) option \e --log-config
-can be used. This configuration file also allows for directing only certain
-messages to a particular output stream and for filtering certain messages
-based on the module or application where they are generated. An example
-configuration file is provided in <em>\<etcdir\>/logger.cfg</em>.
-
-\section stl2dcm_command_line COMMAND LINE
-
-All command line tools use the following notation for parameters: square
-brackets enclose optional values (0-1), three trailing dots indicate that
-multiple values are allowed (1-n), a combination of both means 0 to n values.
-
-Command line options are distinguished from parameters by a leading '+' or '-'
-sign, respectively. Usually, order and position of command line options are
-arbitrary (i.e. they can appear anywhere). However, if options are mutually
-exclusive the rightmost appearance is used. This behavior conforms to the
-standard evaluation rules of common Unix shells.
-
-In addition, one or more command files can be specified using an '@' sign as a
-prefix to the filename (e.g. <em>\@command.txt</em>). Such a command argument
-is replaced by the content of the corresponding text file (multiple
-whitespaces are treated as a single separator unless they appear between two
-quotation marks) prior to any further evaluation. Please note that a command
-file cannot contain another command file. This simple but effective approach
-allows one to summarize common combinations of options/parameters and avoids
-longish and confusing command lines (an example is provided in file
-<em>\<datadir\>/dumppat.txt</em>).
-
-\section stl2dcm_exit_codes EXIT CODES
-
-The \b stl2dcm utility uses the following exit codes when terminating. This
-enables the user to check for the reason why the application terminated.
-
-\subsection stl2dcm_exit_codes_general general
-\verbatim
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-EXITCODE_MEMORY_EXHAUSTED 4
-\endverbatim
-
-\subsection stl2dcm_exit_codes_input_file_errors input file errors
-\verbatim
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-\endverbatim
-
-\subsection stl2dcm_exit_codes_output_file_errors output file errors
-\verbatim
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-\endverbatim
-
-\section stl2dcm_environment ENVIRONMENT
-
-The \b stl2dcm utility will attempt to load DICOM data dictionaries specified
-in the \e DCMDICTPATH environment variable. By default, i.e. if the
-\e DCMDICTPATH environment variable is not set, the file
-<em>\<datadir\>/dicom.dic</em> will be loaded unless the dictionary is built
-into the application (default for Windows).
-
-The default behavior should be preferred and the \e DCMDICTPATH environment
-variable only used when alternative data dictionaries are required. The
-\e DCMDICTPATH environment variable has the same format as the Unix shell
-\e PATH variable in that a colon (":") separates entries. On Windows systems,
-a semicolon (";") is used as a separator. The data dictionary code will
-attempt to load each file specified in the \e DCMDICTPATH environment
-variable.
-It is an error if no data dictionary can be loaded.
+<b>dcmencap</b>(1)
\section stl2dcm_copyright COPYRIGHT
-Copyright (C) 2018-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2018-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section xml2dcm_copyright COPYRIGHT
-Copyright (C) 2003-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2003-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 1994-2019, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/** @name string normalization flags.
* These flags can be used with normalizeString() to specify the extent of normalization.
*/
-//@{
+///@{
/// delete trailing spaces
const OFBool DELETE_TRAILING = OFTrue;
/// handle string as multi-valued (components separated by a backslash)
const OFBool MULTIPART = OFTrue;
-//@}
+///@}
/* Function to get part out of a String for VM > 1 */
/*
*
- * Copyright (C) 1997-2023, OFFIS e.V.
+ * Copyright (C) 1997-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_TransferSyntax oldRepType,
const E_TransferSyntax newRepType) const = 0;
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded with this codec.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const = 0;
+
/** determine color model of the decompressed image
* @param fromParam representation parameter of current compressed
* representation, may be NULL
DcmItem *dataset,
OFString &decompressedColorModel);
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded.
+ * @param fromType transfer syntax to decode from
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ static Uint16 decodedBitsAllocated(
+ const DcmXfer & fromType,
+ Uint16 bitsAllocated,
+ Uint16 bitsStored);
+
private:
/** constructor
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFBool checkForSpecificCharacterSet() const { return OFTrue; }
+ /** initialize the OriginalXfer and CurrentXfer member variables.
+ * This method sets the values for OriginalXfer (i.e. the transfer syntax
+ * in which a dataset is or was originally read) and CurrentXfer
+ * (i.e. the currently active transfer syntax).
+ * The method should only be called during import operations.
+ * @param xfer new value for OriginalXfer and CurrentXfer
+ */
+ void initializeXfer(const E_TransferSyntax xfer);
+
protected:
/** perform checks after reading of the dataset is considered complete. The
/*
*
- * Copyright (C) 2002-2024, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const OFString &referencedFileID,
const OFFilename &sourceFilename);
+ /** create or update waveform presentation state record and copy required values
+ * from dataset
+ * @param record record to be updated, use NULL to create a new one
+ * @param fileformat DICOM dataset of the current file
+ * @param referencedFileID value of the Referenced File ID attribute
+ * @param sourceFilename name of the source DICOM file
+ * @return pointer to new or updated record, NULL if an error occurred
+ */
+ DcmDirectoryRecord *buildWfPresentationRecord(DcmDirectoryRecord *record,
+ DcmFileFormat *fileformat,
+ const OFString &referencedFileID,
+ const OFFilename &sourceFilename);
+
/** create or update waveform record and copy required values from dataset
* @param record record to be updated, use NULL to create a new one
* @param fileformat DICOM dataset of the current file
**
** User: joergr
** Host: thinkpad2
-** Date: 2024-11-16 10:42:04
+** Date: 2025-11-21 11:54:35
** Prog: /home/joergr/Source/dcmtk-full/public/dcmdata/libsrc/mkdeftag
**
** From: ../data/dicom.dic
#include "dcmtk/dcmdata/dctagkey.h"
-#define DCM_DICT_DEFTAG_BUILD_DATE "2024-11-16 10:42:04"
+#define DCM_DICT_DEFTAG_BUILD_DATE "2025-11-21 11:54:35"
/*
** Fixed Tags in ascending (gggg,eeee) order.
-** Number of entries: 5206
+** Number of entries: 5266
** Tags with a repeating component (repeating tags) are listed later.
*/
#define DCM_CommandGroupLength DcmTagKey(0x0000, 0x0000)
#define DCM_FailedStudySequence DcmTagKey(0x0008, 0x119b)
#define DCM_StudiesContainingOtherReferencedInstancesSequence DcmTagKey(0x0008, 0x1200)
#define DCM_RelatedSeriesSequence DcmTagKey(0x0008, 0x1250)
+#define DCM_PrincipalDiagnosisCodeSequence DcmTagKey(0x0008, 0x1301)
+#define DCM_PrimaryDiagnosisCodeSequence DcmTagKey(0x0008, 0x1302)
+#define DCM_SecondaryDiagnosesCodeSequence DcmTagKey(0x0008, 0x1303)
+#define DCM_HistologicalDiagnosesCodeSequence DcmTagKey(0x0008, 0x1304)
#define DCM_RETIRED_LossyImageCompressionRetired DcmTagKey(0x0008, 0x2110)
#define DCM_DerivationDescription DcmTagKey(0x0008, 0x2111)
#define DCM_SourceImageSequence DcmTagKey(0x0008, 0x2112)
#define DCM_RecommendedDisplayFrameRateInFloat DcmTagKey(0x0008, 0x9459)
#define DCM_SkipFrameRangeFlag DcmTagKey(0x0008, 0x9460)
#define DCM_PatientName DcmTagKey(0x0010, 0x0010)
+#define DCM_PersonNamesToUseSequence DcmTagKey(0x0010, 0x0011)
+#define DCM_NameToUse DcmTagKey(0x0010, 0x0012)
+#define DCM_NameToUseComment DcmTagKey(0x0010, 0x0013)
+#define DCM_ThirdPersonPronounsSequence DcmTagKey(0x0010, 0x0014)
+#define DCM_PronounCodeSequence DcmTagKey(0x0010, 0x0015)
+#define DCM_PronounComment DcmTagKey(0x0010, 0x0016)
#define DCM_PatientID DcmTagKey(0x0010, 0x0020)
#define DCM_IssuerOfPatientID DcmTagKey(0x0010, 0x0021)
#define DCM_TypeOfPatientID DcmTagKey(0x0010, 0x0022)
#define DCM_PatientDeathDateInAlternativeCalendar DcmTagKey(0x0010, 0x0034)
#define DCM_PatientAlternativeCalendar DcmTagKey(0x0010, 0x0035)
#define DCM_PatientSex DcmTagKey(0x0010, 0x0040)
+#define DCM_GenderIdentitySequence DcmTagKey(0x0010, 0x0041)
+#define DCM_SexParametersForClinicalUseCategoryComment DcmTagKey(0x0010, 0x0042)
+#define DCM_SexParametersForClinicalUseCategorySequence DcmTagKey(0x0010, 0x0043)
+#define DCM_GenderIdentityCodeSequence DcmTagKey(0x0010, 0x0044)
+#define DCM_GenderIdentityComment DcmTagKey(0x0010, 0x0045)
+#define DCM_SexParametersForClinicalUseCategoryCodeSequence DcmTagKey(0x0010, 0x0046)
+#define DCM_SexParametersForClinicalUseCategoryReference DcmTagKey(0x0010, 0x0047)
#define DCM_PatientInsurancePlanCodeSequence DcmTagKey(0x0010, 0x0050)
#define DCM_PatientPrimaryLanguageCodeSequence DcmTagKey(0x0010, 0x0101)
#define DCM_PatientPrimaryLanguageModifierCodeSequence DcmTagKey(0x0010, 0x0102)
#define DCM_RegionOfResidence DcmTagKey(0x0010, 0x2152)
#define DCM_PatientTelephoneNumbers DcmTagKey(0x0010, 0x2154)
#define DCM_PatientTelecomInformation DcmTagKey(0x0010, 0x2155)
-#define DCM_EthnicGroup DcmTagKey(0x0010, 0x2160)
+#define DCM_RETIRED_EthnicGroup DcmTagKey(0x0010, 0x2160)
#define DCM_EthnicGroupCodeSequence DcmTagKey(0x0010, 0x2161)
+#define DCM_EthnicGroups DcmTagKey(0x0010, 0x2162)
#define DCM_Occupation DcmTagKey(0x0010, 0x2180)
#define DCM_SmokingStatus DcmTagKey(0x0010, 0x21a0)
#define DCM_AdditionalPatientHistory DcmTagKey(0x0010, 0x21b0)
#define DCM_ImageQualityIndicatorType DcmTagKey(0x0014, 0x40a0)
#define DCM_ImageQualityIndicatorMaterial DcmTagKey(0x0014, 0x40a1)
#define DCM_ImageQualityIndicatorSize DcmTagKey(0x0014, 0x40a2)
+#define DCM_WaveDimensionsDefinitionSequence DcmTagKey(0x0014, 0x4101)
+#define DCM_WaveDimensionNumber DcmTagKey(0x0014, 0x4102)
+#define DCM_WaveDimensionDescription DcmTagKey(0x0014, 0x4103)
+#define DCM_WaveDimensionUnit DcmTagKey(0x0014, 0x4104)
+#define DCM_WaveDimensionValueType DcmTagKey(0x0014, 0x4105)
+#define DCM_WaveDimensionValuesSequence DcmTagKey(0x0014, 0x4106)
+#define DCM_ReferencedWaveDimension DcmTagKey(0x0014, 0x4107)
+#define DCM_IntegerNumericValue DcmTagKey(0x0014, 0x4108)
+#define DCM_ByteNumericValue DcmTagKey(0x0014, 0x4109)
+#define DCM_ShortNumericValue DcmTagKey(0x0014, 0x410a)
+#define DCM_SinglePrecisionFloatingPointNumericValue DcmTagKey(0x0014, 0x410b)
+#define DCM_DoublePrecisionFloatingPointNumericValue DcmTagKey(0x0014, 0x410c)
#define DCM_LINACEnergy DcmTagKey(0x0014, 0x5002)
#define DCM_LINACOutput DcmTagKey(0x0014, 0x5004)
#define DCM_ActiveAperture DcmTagKey(0x0014, 0x5100)
#define DCM_VerificationDateTime DcmTagKey(0x0040, 0xa030)
#define DCM_ObservationDateTime DcmTagKey(0x0040, 0xa032)
#define DCM_ObservationStartDateTime DcmTagKey(0x0040, 0xa033)
+#define DCM_EffectiveStartDateTime DcmTagKey(0x0040, 0xa034)
+#define DCM_EffectiveStopDateTime DcmTagKey(0x0040, 0xa035)
#define DCM_ValueType DcmTagKey(0x0040, 0xa040)
#define DCM_ConceptNameCodeSequence DcmTagKey(0x0040, 0xa043)
#define DCM_RETIRED_MeasurementPrecisionDescriptionTrial DcmTagKey(0x0040, 0xa047)
#define DCM_CellValuesSequence DcmTagKey(0x0040, 0xa808)
#define DCM_RETIRED_UniformResourceLocatorTrial DcmTagKey(0x0040, 0xa992)
#define DCM_WaveformAnnotationSequence DcmTagKey(0x0040, 0xb020)
+#define DCM_StructuredWaveformAnnotationSequence DcmTagKey(0x0040, 0xb030)
+#define DCM_WaveformAnnotationDisplaySelectionSequence DcmTagKey(0x0040, 0xb031)
+#define DCM_ReferencedMontageIndex DcmTagKey(0x0040, 0xb032)
+#define DCM_WaveformTextualAnnotationSequence DcmTagKey(0x0040, 0xb033)
+#define DCM_AnnotationDateTime DcmTagKey(0x0040, 0xb034)
+#define DCM_DisplayedWaveformSegmentSequence DcmTagKey(0x0040, 0xb035)
+#define DCM_SegmentDefinitionDateTime DcmTagKey(0x0040, 0xb036)
+#define DCM_MontageActivationSequence DcmTagKey(0x0040, 0xb037)
+#define DCM_MontageActivationTimeOffset DcmTagKey(0x0040, 0xb038)
+#define DCM_WaveformMontageSequence DcmTagKey(0x0040, 0xb039)
+#define DCM_ReferencedMontageChannelNumber DcmTagKey(0x0040, 0xb03a)
+#define DCM_MontageName DcmTagKey(0x0040, 0xb03b)
+#define DCM_MontageChannelSequence DcmTagKey(0x0040, 0xb03c)
+#define DCM_MontageIndex DcmTagKey(0x0040, 0xb03d)
+#define DCM_MontageChannelNumber DcmTagKey(0x0040, 0xb03e)
+#define DCM_MontageChannelLabel DcmTagKey(0x0040, 0xb03f)
+#define DCM_MontageChannelSourceCodeSequence DcmTagKey(0x0040, 0xb040)
+#define DCM_ContributingChannelSourcesSequence DcmTagKey(0x0040, 0xb041)
+#define DCM_ChannelWeight DcmTagKey(0x0040, 0xb042)
#define DCM_TemplateIdentifier DcmTagKey(0x0040, 0xdb00)
#define DCM_RETIRED_TemplateVersion DcmTagKey(0x0040, 0xdb06)
#define DCM_RETIRED_TemplateLocalVersion DcmTagKey(0x0040, 0xdb07)
#define DCM_ReferencedAssertionUID DcmTagKey(0x0044, 0x0108)
#define DCM_ApprovalSubjectSequence DcmTagKey(0x0044, 0x0109)
#define DCM_OrganizationalRoleCodeSequence DcmTagKey(0x0044, 0x010a)
+#define DCM_RTAssertionsSequence DcmTagKey(0x0044, 0x0110)
#define DCM_LensDescription DcmTagKey(0x0046, 0x0012)
#define DCM_RightLensSequence DcmTagKey(0x0046, 0x0014)
#define DCM_LeftLensSequence DcmTagKey(0x0046, 0x0015)
#define DCM_PixelOriginInterpretation DcmTagKey(0x0048, 0x0301)
#define DCM_NumberOfOpticalPaths DcmTagKey(0x0048, 0x0302)
#define DCM_TotalPixelMatrixFocalPlanes DcmTagKey(0x0048, 0x0303)
+#define DCM_TilesOverlap DcmTagKey(0x0048, 0x0304)
#define DCM_CalibrationImage DcmTagKey(0x0050, 0x0004)
#define DCM_DeviceSequence DcmTagKey(0x0050, 0x0010)
#define DCM_ContainerComponentTypeCodeSequence DcmTagKey(0x0050, 0x0012)
#define DCM_DVHMinimumDose DcmTagKey(0x3004, 0x0070)
#define DCM_DVHMaximumDose DcmTagKey(0x3004, 0x0072)
#define DCM_DVHMeanDose DcmTagKey(0x3004, 0x0074)
+#define DCM_DoseCalculationModelSequence DcmTagKey(0x3004, 0x0080)
+#define DCM_DoseCalculationAlgorithmSequence DcmTagKey(0x3004, 0x0081)
+#define DCM_CommissioningStatus DcmTagKey(0x3004, 0x0082)
+#define DCM_DoseCalculationModelParameterSequence DcmTagKey(0x3004, 0x0083)
+#define DCM_DoseDepositionCalculationMedium DcmTagKey(0x3004, 0x0084)
#define DCM_StructureSetLabel DcmTagKey(0x3006, 0x0002)
#define DCM_StructureSetName DcmTagKey(0x3006, 0x0004)
#define DCM_StructureSetDescription DcmTagKey(0x3006, 0x0006)
#define DCM_ScanningSpotSize DcmTagKey(0x300a, 0x0398)
#define DCM_ScanSpotSizesDelivered DcmTagKey(0x300a, 0x0399)
#define DCM_NumberOfPaintings DcmTagKey(0x300a, 0x039a)
+#define DCM_ScanSpotGantryAngles DcmTagKey(0x300a, 0x039b)
+#define DCM_ScanSpotPatientSupportAngles DcmTagKey(0x300a, 0x039c)
#define DCM_IonToleranceTableSequence DcmTagKey(0x300a, 0x03a0)
#define DCM_IonBeamSequence DcmTagKey(0x300a, 0x03a2)
#define DCM_IonBeamLimitingDeviceSequence DcmTagKey(0x300a, 0x03a4)
/*
*
- * Copyright (C) 1994-2023, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/// annotation
ERT_Annotation = 49,
/// inventory
- ERT_Inventory = 50
+ ERT_Inventory = 50,
+ /// wf presentation
+ ERT_WfPresentation = 51
} E_DirRecType;
--- /dev/null
+/*
+ *
+ * Copyright (C) 2007-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Marco Eichelberg, Tingyan Xu
+ *
+ * Purpose: Helper class for extracting encapsulated file from DICOM encapsulated storage object
+ *
+ */
+
+#ifndef DCDOCDEC_H
+#define DCDOCDEC_H
+
+#include "dcmtk/config/osconfig.h"
+#include "dcmtk/dcmdata/dcdefine.h" /* for DCMTK_DCMDATA_EXPORT */
+#include "dcmtk/dcmdata/dcfilefo.h" /* for DcmFileFormat */
+
+/** Helper class for extracting the encapsulated document from a
+ * DICOM encapsulated storage object to file
+ */
+class DCMTK_DCMDATA_EXPORT DcmDocumentDecapsulator
+{
+public:
+ /// Constructor
+ DcmDocumentDecapsulator();
+
+ /// Destructor
+ virtual ~DcmDocumentDecapsulator();
+
+ /** set the read mode for reading a DICOM file (default: ERM_autoDetect)
+ * @param mode new read mode
+ */
+ void setReadMode(E_FileReadMode mode)
+ {
+ readMode_ = mode;
+ }
+
+ /** set the input transfer syntax for reading a DICOM file (default: EXS_Unknown)
+ * @param xfer new input transfer syntax
+ */
+ void setInputXferSyntax(E_TransferSyntax xfer)
+ {
+ inputXfer_ = xfer;
+ }
+
+ /** set a command line string to be executed after the encapsulated document has been written to file
+ * @param execString command line string
+ */
+ void setExecString(const char *execString)
+ {
+ execString_ = execString;
+ }
+
+ /** set the filename (path) for the DICOM file to be read
+ * @param fname input file name
+ */
+ void setInputFile(const char *fname)
+ {
+ inputFname_ = fname;
+ }
+
+ /** set the filename (path) for the output file to be written
+ * @param fname output file name
+ */
+ void setOutputFile(const char *fname)
+ {
+ outputFname_ = fname;
+ }
+
+ /** load the encapsulated DICOM file into memory.
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ OFCondition loadDICOMFile();
+
+ /** extract the encapsulated document, remove a pad byte if necessary,
+ * and write the document to the output file
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ OFCondition writeEncapsulatedContentToFile();
+
+ /** execute the pre-defined command line, replacing the placeholder
+ * "#f" with the actual output filename.
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ OFCondition executeCommand();
+
+private:
+
+ /// input file read mode
+ E_FileReadMode readMode_;
+
+ /// input transfer syntax
+ E_TransferSyntax inputXfer_;
+
+ /// command line string to be executed
+ const char *execString_;
+
+ /// input filename
+ const char *inputFname_;
+
+ /// output filename
+ const char *outputFname_;
+
+ /// DICOM file
+ DcmFileFormat dicomFile_;
+
+};
+
+#endif // DCDOCDEC_H
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFCondition putFloat32(const Float32 val, const unsigned long pos = 0);
+ /** insert into the element value a copy of the given Sint64 value. If the
+ * attribute is multi-valued, all other values remain untouched.
+ * Requires element to be of corresponding VR, otherwise an error is returned.
+ * @param val new value to be inserted
+ * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value
+ * can be appended to the end of the current element or inserted within the
+ * existing value field.
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition putSint64(const Sint64 val, const unsigned long pos = 0);
+
+ /** insert into the element value a copy of the given Uint64 value. If the
+ * attribute is multi-valued, all other values remain untouched.
+ * Requires element to be of corresponding VR, otherwise an error is returned.
+ * @param val new value to be inserted
+ * @param pos position for insert operation. Value: pos <= getVM(), i.e. a value
+ * can be appended to the end of the current element or inserted within the
+ * existing value field.
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition putUint64(const Uint64 val, const unsigned long pos = 0);
+
/** insert into the element value a copy of the given Float64 value. If the
* attribute is multi-valued, all other values remain untouched.
* Requires element to be of corresponding VR, otherwise an error is returned.
*/
virtual OFCondition putTagVal(const DcmTagKey &attrTag, const unsigned long pos = 0);
- /** replace the element value by a copy of the given Uint8 array (which is possibly multi-valued).
+ /** replace the element value by a copy of the given Uint8 array (which is
+ * possibly multi-valued).
* Requires element to be of corresponding VR, otherwise an error is returned.
* @param vals new attribute value
* @param num number of values in array vals
*/
virtual OFCondition putUint8Array(const Uint8 *vals, const unsigned long num);
- /** replace the element value by a copy of the given Sint16 array (which is possibly multi-valued).
+ /** replace the element value by a copy of the given Sint16 array (which is
+ * possibly multi-valued).
* Requires element to be of corresponding VR, otherwise an error is returned.
* @param vals new attribute value
* @param num number of values in array vals
*/
virtual OFCondition putSint16Array(const Sint16 *vals, const unsigned long num);
- /** replace the element value by a copy of the given Uint16 array (which is possibly multi-valued).
+ /** replace the element value by a copy of the given Uint16 array (which is
+ * possibly multi-valued).
* Requires element to be of corresponding VR, otherwise an error is returned.
* @param vals new attribute value
* @param num number of values in array vals
*/
virtual OFCondition putUint16Array(const Uint16 *vals, const unsigned long num);
- /** replace the element value by a copy of the given Sint32 array (which is possibly multi-valued).
+ /** replace the element value by a copy of the given Sint32 array (which is
+ * possibly multi-valued).
* Requires element to be of corresponding VR, otherwise an error is returned.
* @param vals new attribute value
* @param num number of values in array vals
*/
virtual OFCondition putSint32Array(const Sint32 *vals, const unsigned long num);
- /** replace the element value by a copy of the given Uint32 array (which is possibly multi-valued).
+ /** replace the element value by a copy of the given Uint32 array (which is
+ * possibly multi-valued).
* Requires element to be of corresponding VR, otherwise an error is returned.
* @param vals new attribute value
* @param num number of values in array vals
*/
virtual OFCondition putUint32Array(const Uint32 *vals, const unsigned long num);
- /** replace the element value by a copy of the given Float32 array (which is possibly multi-valued).
+ /** replace the element value by a copy of the given Float32 array (which is
+ * possibly multi-valued).
* Requires element to be of corresponding VR, otherwise an error is returned.
* @param vals new attribute value
* @param num number of values in array vals
*/
virtual OFCondition putFloat32Array(const Float32 *vals, const unsigned long num);
- /** replace the element value by a copy of the given Float64 array (which is possibly multi-valued).
+ /** replace the element value by a copy of the given Sint64 array (which is
+ * possibly multi-valued).
+ * Requires element to be of corresponding VR, otherwise an error is returned.
+ * @param vals new attribute value
+ * @param num number of values in array vals
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition putSint64Array(const Sint64 *vals, const unsigned long num);
+
+ /** replace the element value by a copy of the given Uint64 array (which is
+ * possibly multi-valued).
+ * Requires element to be of corresponding VR, otherwise an error is returned.
+ * @param vals new attribute value
+ * @param num number of values in array vals
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition putUint64Array(const Uint64 *vals, const unsigned long num);
+
+ /** replace the element value by a copy of the given Float64 array (which is
+ * possibly multi-valued).
* Requires element to be of corresponding VR, otherwise an error is returned.
* @param vals new attribute value
* @param num number of values in array vals
static OFCondition checkVM(const unsigned long vmNum,
const OFString &vmStr);
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return effective value of BitsAllocated, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
protected:
/** This function returns this element's value. The returned value corresponds to the
/*
*
- * Copyright (C) 2018-2021, OFFIS e.V.
+ * Copyright (C) 2018-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* Module: dcmdata
*
- * Author: Pedro Arizpe
+ * Author: Pedro Arizpe, Marco Eichelberg
*
* Purpose: Class to control document encapsulation into DICOM files
*
#ifndef DCENCDOC_H
#define DCENCDOC_H
-//make sure OS specific configuration is included first
-#include "dcmtk/config/osconfig.h"
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/ofstring.h" /* for class OFString */
#include "dcmtk/ofstd/ofcond.h" /* for class OFCondition */
#include "dcmtk/dcmdata/dcdefine.h" /* for DCMTK_DCMDATA_EXPORT */
#include "dcmtk/dcmdata/dcfilefo.h" /* for class DcmFileFormat */
#include "dcmtk/ofstd/ofcmdln.h" /* for OFCmdUnsignedInt */
-struct XMLNode;
class OFCommandLine;
class OFConsoleApplication;
-class OFLogger;
+class DcmItem;
-/** This class handles common functions of all command line applications
- * for document encapsulation.
+/** This class handles common functions for the conversion of
+ * documents into encapsulated DICOM SOP instances.
*/
class DCMTK_DCMDATA_EXPORT DcmEncapsulatedDocument
{
public:
- ///Constructor
- DcmEncapsulatedDocument();
-
- ///Destructor
- ~DcmEncapsulatedDocument();
-
- /** This function is only used to process CDA files.
- * It retrieves all entries of an attribute and returns them separated by backslashes.
- * @param fileNode the root XML node.
- * @param attr the attribute to search for.
- * @return OFstring containing all entries found, separated by double backslashes
- */
- OFString XMLgetAllAttributeValues(XMLNode fileNode, OFString attr);
-
- /** This function is only used to process CDA files.
- * It retrieves the value from the CDA document
- * corresponding to the DCM Tag. According to Standard v. 2013 part20/sect_A.8.
- * @param fileNode the root XML node.
- * @param attr the tag to search for in the CDA file.
- * @return OFstring containing the value of the corresponding tag.
- */
- OFString XMLgetAttribute(XMLNode fileNode, DcmTagKey attr);
-
- /** Retrieves patient, concept and document data from the CDA file and checks for data conflicts
- * with series, study and user input. It also retrieves all mediatypes found in the CDA document.
- * @param filename The filename of the CDA document.
- * @param appLogger The logger of the application calling this method.
- * @return EXITCODE_NO_ERROR (0) if successful or error code in case of failure.
- */
- int getCDAData(const char *filename, OFLogger &appLogger);
-
- /** Recursive function used by getAttributeValues to get all occurrences of an attribute as list.
- * @param currnode the current XML node to be processed.
- * @param results a pointer to the list of strings where the results should be stored.
- * @param attr the attribute to search for.
- * @return OFTrue if the attribute value was found, OFFalse otherwise.
- */
- OFBool XMLsearchAttribute(XMLNode currnode, OFList<OFString> *results, OFString attr);
-
- /** Add CDA specific command line options to the OFCommandLine object
- * passed to the constructor.
- * @param cmd a reference to an OFCommandLine object used to parse
- * the command line argument give to the calling application.
- * @return none.
- */
- void addCDACommandlineOptions(OFCommandLine& cmd);
-
- /** Add PDF specific command line options to the OFCommandLine object
- * passed to the constructor.
- * @param cmd a reference to an OFCommandLine object used to parse
- * the command line argument give to the calling application.
- * @return none.
- */
- void addPDFCommandlineOptions(OFCommandLine& cmd);
-
- /** Add STL specific command line options to the OFCommandLine object
- * passed to the constructor.
- * @param cmd a reference to an OFCommandLine object used to parse
- * the command line argument give to the calling application.
- * @return none.
- */
- void addSTLCommandlineOptions(OFCommandLine& cmd);
-
- /** Add general command line options to the OFCommandLine object
- * passed to the constructor.
- * @param cmd a reference to an OFCommandLine object used to parse
- * the command line argument give to the calling application.
- * @return none.
- */
- void addGeneralOptions(OFCommandLine &cmd);
-
- /** Add command line options specific for documents to the OFCommandLine
- * object passed to the constructor.
- * @param cmd a reference to an OFCommandLine object used to parse
- * the command line argument give to the calling application.
- * @return none.
- */
- void addDocumentOptions(OFCommandLine &cmd);
-
- /** Add command line options specific for output to the OFCommandLine
- * object passed to the constructor.
- * @param cmd a reference to an OFCommandLine object used to parse
- * the command line argument give to the calling application.
- * @return none.
- */
- void addOutputOptions(OFCommandLine &cmd);
-
- /** Parse and evaluate the given command line arguments.
- * @param app a reference to an OFConsoleApplication object used in the
- * calling application.
- * @param cmd a reference to an OFCommandLine object used to parse
- * the command line argument give to the calling application.
- * @return none.
- */
- void parseArguments(OFConsoleApplication& app, OFCommandLine& cmd);
-
- /** Includes basic information into the DICOM file.
- * @param dataset a reference to a DcmItem containing the information to be included.
- * @param logger The logger of the application calling this method.
- * @return EC_Normal if successful, an error code otherwise.
- */
- OFCondition createHeader (DcmItem *dataset,
- OFLogger& logger);
-
- /** Correctly inserts encapsulated document data.
- * @param dataset The dataset to which we should encapsulate this document.
- * @param logger The logger of the application calling this method.
- * @return EXITCODE_NO_ERROR (0) if successful or error code in case of failure.
- */
- int insertEncapsulatedDocument(DcmItem *dataset,
- OFLogger& logger);
-
- /** Get study or series data from provided file. Generate UID if none present.
- * @param appLogger The logger of the application calling this method.
- * @return EC_Normal if successful, an error code otherwise.
- */
- OFCondition createIdentifiers(OFLogger& appLogger);
-
- /** Copy override keys over existing keys in given dataset.
- * @param outputDset dataset to which the override keys are copied
- * @return EC_Normal if successful, an error code otherwise.
- */
- OFCondition applyOverrideKeys(DcmDataset *outputDset);
-
- /** Specifies some attributes that should be inserted after encapsulation
- * They will override any identical attributes already existing in the resulting encapsulated
- * DICOM object. The override keys are applied at the very end of the conversion and do not
- * undergo any validity checking.
- * @param ovkeys override keys that can be tags, dictionary names and paths (see DcmPath
- * for syntax). Also it is permitted to set a value if appropriate, e. g. "PatientName=Doe^John"
- * would be a valid overridekey.
- * @return none.
- */
- void setOverrideKeys(const OFList<OFString>& ovkeys);
-
- /** Returns the input file name.
- * @return the input file name as OFString.
- */
- OFString getInputFileName();
-
- /** Sets the input file name to the given string.
- * @param fName the file name to be set.
- * @return none.
- */
- void setInputFileName(OFString fName);
-
- /** Returns the output file name.
- * @return the output file name as OFString.
- */
- OFString getOutputFileName();
-
- /** Sets the output file name.
- * @param fName the file name to be set.
- * @return none.
- */
- void setOutputFileName(OFString fName);
-
- /** Attempt to save the output file .
- * @param fileformat the DICOM Fileformat including the output file params.
- * @return Error code as condition, if error occurs, EC_Normal otherwise.
- */
- OFCondition saveFile(DcmFileFormat fileformat);
-
- /** Returns the transfer syntax.
- * @return the transfer syntax as E_TransferSyntax.
- */
- E_TransferSyntax getTransferSyntax();
-
- /** Returns the current filetype.
- * @return the current filetype as OFString.
- */
- OFString getFileType();
-
- /** Sets the current filetype.
- * @param fType the current filetype.
- * @return none.
- */
- void setFileType(OFString fType);
+
+ /// document type of encapsulated document
+ enum DocumentType
+ {
+ /// PDF document
+ DT_pdfDocument,
+ /// CDA document
+ DT_cdaDocument,
+ /// STL document
+ DT_stlDocument,
+ /// MTL document
+ DT_mtlDocument,
+ /// OBJ document
+ DT_objDocument,
+ /// unknown document
+ DT_unknownDocument,
+ };
+
+ ///Constructor
+ DcmEncapsulatedDocument();
+
+ ///Destructor
+ ~DcmEncapsulatedDocument();
+
+ /** Add CDA specific command line options to the OFCommandLine object
+ * passed to the constructor.
+ * @param cmd a reference to an OFCommandLine object used to parse
+ * the command line argument give to the calling application.
+ * @return none.
+ */
+ void addCommandlineOptions(OFCommandLine& cmd) const;
+
+ /** Parse and evaluate the given command line arguments.
+ * @param app a reference to an OFConsoleApplication object used in the
+ * calling application.
+ * @param cmd a reference to an OFCommandLine object used to parse
+ * the command line argument give to the calling application.
+ * @return none.
+ */
+ void parseArguments(OFConsoleApplication& app, OFCommandLine& cmd);
+
+ /** Identify document format and insert encapsulated document data
+ * into the dataset
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition insertEncapsulatedDocument();
+
+ /** Get study or series data from series file. Generate UID if none present.
+ * @note This method should be called after insertEncapsulatedDocument()
+ * to make sure that the document format has been identified.
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition createIdentifiers();
+
+ /** Perform format specific processing such as extracting information
+ * from the document content.
+ * @note This method should be called after insertEncapsulatedDocument()
+ * and after createIdentifiers() to make sure that the document format
+ * has been identified and inconsistencies between DICOM and document
+ * level can be checked.
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition formatSpecificProcessing();
+
+ /** Write header fields to the DICOM dataset
+ * @note This method should be called after insertEncapsulatedDocument()
+ * to make sure that the document format has been identified.
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition createHeader();
+
+ /** Copy override keys over existing keys in given dataset.
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition applyOverrideKeys();
+
+ /** Returns the input file name.
+ * @return the input file name as OFString.
+ */
+ OFString getInputFileName();
+
+ /** Returns the output file name.
+ * @return the output file name as OFString.
+ */
+ OFString getOutputFileName();
+
+ /** Save the output file.
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition saveFile();
private:
- ///input file name
- OFString opt_ifname;
- ///output file name
- OFString opt_ofname;
-
- ///optional parameters
- ///*patient data
- OFString opt_patientBirthdate;
- OFString opt_patientID;
- OFString opt_patientName;
- OFString opt_patientSex;
- ///*concept data
- OFString opt_conceptCM;
- OFString opt_conceptCSD;
- OFString opt_conceptCV;
- ///*document specific options
- OFString opt_documentTitle;
- OFString opt_seriesFile;
- OFString opt_seriesUID;
- OFString opt_studyUID;
-
- ///*assign default values for file encoding and padding
- E_EncodingType opt_oenctype;
- E_FileWriteMode opt_writeMode;
- E_GrpLenEncoding opt_oglenc;
- E_PaddingEncoding opt_opadenc;
- E_TransferSyntax opt_oxfer;
- OFCmdUnsignedInt opt_filepad;
- OFCmdUnsignedInt opt_itempad;
- ///*pre-existing series
- OFBool opt_readSeriesInfo;
- OFBool opt_annotation;
- OFBool opt_increment;
-
- OFCmdSignedInt opt_instance;
- /** These attributes are applied to the dataset after conversion
- * (They are not checked by the isValid() function).
- */
- OFList<OFString> opt_overrideKeys;
-
- ///CDA specific variables
- OFString cda_mediaTypes;
- OFString hl7_InstanceIdentifier;
- OFBool opt_override;
-
- /// STL specific variables
- /// Frame of Reference module
- OFString opt_frameOfReferenceUID;
- OFString opt_positionReferenceIndicator;
- ///Enhanced general equipment module
- /// Manufacturer (VM 1)
- OFString opt_manufacturer;
- /// Manufacturer's Model Name (VM 1)
- OFString opt_manufacturerModelName;
- /// Device Serial Number (VM 1)
- OFString opt_deviceSerialNumber;
- /// Software Version(s) (VM 1-n)
- OFString opt_softwareVersions;
-
- /// Manufacturing 3D Model Module
- /// 3d Model Measurement Units Code Meaning
- OFString opt_measurementUnitsCM;
- /// 3d Model Measurement Units Code Scheme Designator
- OFString opt_measurementUnitsCSD;
- /// 3d Model Measurement Units Code Value
- OFString opt_measurementUnitsCV;
-
- ///Type of file currently being converted.
- OFString ftype;
+
+ /** Retrieve patient, concept and document data from a CDA file and check for conflicts
+ * with series, study and user input. Also retrieve all mediatypes found in the CDA document.
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition getCDAData();
+
+ /** Add mandatory Frame of Reference Module attributes to dataset.
+ * @param dataset output dataset
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition addFrameOfReferenceModule(DcmItem *dataset);
+
+ /** Add mandatory Enhanced General Equipment Module attributes to dataset.
+ * @param dataset output dataset
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition addEnhancedGeneralEquipmentModule(DcmItem *dataset);
+
+ /** Add mandatory Manufacturing 3D Model Module attributes to dataset.
+ * @param dataset output dataset
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ OFCondition addManufacturing3DModelModule(DcmItem *dataset);
+
+ ///input file name
+ OFString ifname_;
+
+ ///output file name
+ OFString ofname_;
+
+ /// patient's birth date
+ OFString patientBirthdate_;
+
+ /// patient ID
+ OFString patientID_;
+
+ /// patient name
+ OFString patientName_;
+
+ /// patient's sex
+ OFString patientSex_;
+
+ /// document title: code meaning
+ OFString conceptCM_;
+
+ /// document title: code scheme designator
+ OFString conceptCSD_;
+
+ /// document title: code value
+ OFString conceptCV_;
+
+ /// document title
+ OFString documentTitle_;
+
+ /// file to read series data from
+ OFString seriesFile_;
+
+ /// series instance UID
+ OFString seriesUID_;
+
+ /// study instance UID
+ OFString studyUID_;
+
+ /// specific character set (from series file)
+ OFString specificCharSet_;
+
+ /// modality (from series file)
+ OFString modality_;
+
+ /// DICOM sequence encoding: explicit or undefined length
+ E_EncodingType oenctype_;
+
+ /// write mode for the DICOM file
+ E_FileWriteMode writeMode_;
+
+ /// handling of group length encoding
+ E_GrpLenEncoding oglenc_;
+
+ /// handling of data set trailing padding
+ E_PaddingEncoding opadenc_;
+
+ /// transfer syntax for the DICOM file
+ E_TransferSyntax oxfer_;
+
+ /// padding for the main dataset
+ OFCmdUnsignedInt filepad_;
+
+ /// padding for sequence items
+ OFCmdUnsignedInt itempad_;
+
+ /// true if we are supposed to read series information from another DICOM file
+ OFBool readSeriesInfo_;
+
+ /// burned-in annotation present?
+ OFBool annotation_;
+
+ /// increment instance number from given DICOM series file?
+ OFBool increment_;
+
+ /// instance number
+ OFCmdSignedInt instance_;
+
+ /// list of DICOM attributes and attribute values to be applied after conversion
+ OFList<OFString> overrideKeys_;
+
+ // CDA specific variables
+
+ /// CDA media types
+ OFString cda_mediaTypes;
+
+ /// CDA instance identifier
+ OFString hl7_InstanceIdentifier;
+
+ /// should CDA header values override DICOM values?
+ OFBool override_;
+
+ // STL/MTL/OBJ specific variables
+ // Frame of Reference module
+
+ /// frame of reference UID
+ OFString frameOfReferenceUID_;
+
+ /// position reference indicator
+ OFString positionReferenceIndicator_;
+
+ // Enhanced general equipment module
+
+ /// manufacturer
+ OFString manufacturer_;
+
+ /// manufacturer's model name
+ OFString manufacturerModelName_;
+
+ /// device serial number
+ OFString deviceSerialNumber_;
+
+ /// software version(s) (VM 1-n)
+ OFString softwareVersions_;
+
+ // Manufacturing 3D Model Module
+
+ /// 3D model measurement units code meaning
+ OFString measurementUnitsCM_;
+
+ /// 3D model measurement units code scheme designator
+ OFString measurementUnitsCSD_;
+
+ /// 3D model measurement units code value
+ OFString measurementUnitsCV_;
+
+ /// Type of file currently being converted.
+ DocumentType ftype_;
+
+ /// DICOM file
+ DcmFileFormat dfile_;
};
+
#endif // DCENCDOC_H
/*
*
- * Copyright (C) 1994-2022, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* These constants can be used in addition to the general purpose ones
* defined in module ofstd.
*/
-//@{
+///@{
+
/// Invalid tag
extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidTag;
/// Tag not found
extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_XMLParseError;
/// XML validation failure
extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_XMLValidationFailure;
-/// SOP class mismatch
+/// SOP Class mismatch
extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_SOPClassMismatch;
/// Unknown UID name: No mapping to UID value defined
extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_UnknownUIDName;
/// Cannot write IS/DS string as JSON number
-extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotWriteStringAsJsonNumber;
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotWriteStringAsJSONNumber;
+/// Cannot write bulk data file
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotWriteBulkDataFile;
+/// JSON encoding not supported for encapsulated multi-frame pixel data
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CannotWriteJSONMultiframe;
+/// Not the expected Type while parsing the JSON file
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidJSONType;
+/// Invalid JSON content
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_InvalidJSONContent;
+/// BulkDataURI not yet supported
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_BulkDataURINotSupported;
+/// Unsupported URI type
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_UnsupportedURIType;
+/// Execution of command line failed
+extern DCMTK_DCMDATA_EXPORT const OFConditionConst EC_CommandLineFailed;
-//@}
+///@}
-// status code constants
+/** @name status code constants for module dcmdata.
+ */
+///@{
/// error, cannot select specific character set
extern DCMTK_DCMDATA_EXPORT const unsigned short EC_CODE_CannotSelectCharacterSet;
/// error, cannot determine start fragment (of compressed pixel data)
extern DCMTK_DCMDATA_EXPORT const unsigned short EC_CODE_CannotDetermineStartFragment;
+///@}
+
#endif /* !DCERROR_H */
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#define DCFILEFO_H
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-
#include "dcmtk/dcmdata/dcsequen.h"
#include "dcmtk/dcmdata/dcdatset.h"
-
// forward declarations
class DcmMetaInfo;
class DcmJsonFormat;
FileReadMode = readMode;
}
+ /** set Implementation Class UID to be used when writing the file
+ * (unless the write mode EWM_dontUpdateMeta is used,
+ * in which case the metaheader is not updated.)
+ * @param implementationClassUID implementation class UID
+ */
+ void setImplementationClassUID(const OFString& implementationClassUID);
+
+ /** set Implementation Version Name to be used when writing the file
+ * (unless the write mode EWM_dontUpdateMeta is used,
+ * in which case the metaheader is not updated.)
+ * @param implementationVersionName implementation version name
+ */
+ void setImplementationVersionName(const OFString& implementationVersionName);
+
/** method inherited from base class that shall not be used for instances of this class.
* Method immediately returns with error code.
* @param item item
* @param writeMode flag indicating whether to update the file meta information or not
* @return EC_Normal if successful, an error code otherwise
*/
- static OFCondition checkMetaHeaderValue(DcmMetaInfo *metainfo,
+ OFCondition checkMetaHeaderValue(DcmMetaInfo *metainfo,
DcmDataset *dataset,
const DcmTagKey &atagkey,
DcmObject *obj,
const E_TransferSyntax oxfer,
- const E_FileWriteMode writeMode);
+ const E_FileWriteMode writeMode) const;
/** read DCM_TransferSyntaxUID from meta header dataset and return as E_TransferSyntax value
* @param metainfo meta-header dataset
/// file read mode, specifies whether to read the meta header or not
E_FileReadMode FileReadMode;
+
+ /// implementation class UID to write in the meta-header
+ OFString ImplementationClassUID;
+
+ /// implementation version name to write in the meta-header
+ OFString ImplementationVersionName;
};
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* (separated by a backslash) code extension techniques are used and escape sequences
* may be encountered in the source string to switch between the specified character
* sets.
+ * @note The conversion code does not perform a thorough validation of the strings to
+ * be converted. For example, characters that are permitted in the source character
+ * set but forbidden in DICOM (such as byte positions 0x80-0x9F in ISO_IR 100) may
+ * be converted without warning or error.
* @param fromCharset name of the source character set(s) used for the conversion
* @param toCharset name of the destination character set used for the conversion.
* Only a single value is permitted (i.e. no code extensions).
* character set can be found in the DICOM standard, e.g. "ISO_IR 100" for ISO 8859-1
* (Latin 1) or "ISO_IR 192" for Unicode in UTF-8. An empty string denotes the
* default character repertoire, which is ASCII (7-bit).
+ * @note The conversion code does not perform a thorough validation of the strings to
+ * be converted. For example, characters that are permitted in the source character
+ * set but forbidden in DICOM (such as byte positions 0x80-0x9F in ISO_IR 100) may
+ * be converted without warning or error.
* @param toCharset name of the destination character set used for the conversion.
* Only a single value is permitted (i.e. no code extensions).
* @param flags optional flag used to customize the conversion (see DCMTypes::CF_xxx)
- * @param ignoreCharset if OFTrue, the value of SpecificCharacterSet is ignored.
- * Also see checkForSpecificCharacterSet().
+ * @param ignoreCharset if OFTrue, the value of SpecificCharacterSet is ignored,
+ * otherwise the element value is updated. Also see checkForSpecificCharacterSet().
* @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition convertCharacterSet(const OFString &toCharset,
/** convert all element values that are contained in this item and that are affected
* by SpecificCharacterSet from the currently selected source character set to the
- * currently selected destination character set
+ * currently selected destination character set.
+ * @note The conversion code does not perform a thorough validation of the strings to
+ * be converted. For example, characters that are permitted in the source character
+ * set but forbidden in DICOM (such as byte positions 0x80-0x9F in ISO_IR 100) may
+ * be converted without warning or error.
* @param converter character set converter to be used to convert the element values
* @return status, EC_Normal if successful, an error code otherwise
*/
*/
virtual OFCondition convertToUTF8();
+ /** update the SpecificCharacterSet (0008,0005) element depending on the given
+ * parameters. The current value of this element is either replaced or a new
+ * element is inserted or the existing element is deleted.
+ * @note This method is called by convertCharacterSet() and convertToUTF8() when
+ * needed, so there is usually no reason to call it directly.
+ * @param status error status of previous operations (might also be updated)
+ * @param converter character set converter used to convert element values
+ */
+ virtual void updateSpecificCharacterSet(OFCondition &status,
+ const DcmSpecificCharacterSet &converter);
+
/** insert a new element into the list of elements maintained by this item.
* The list of elements is always kept in ascending tag order.
* @param elem element to be inserted, must not be contained in this or
/* --- findAndGet functions: find an element and get it or the value, respectively --- */
/** find element and get a pointer to it (or copy it).
- * Applicable to all DICOM value representations (VR).
* The result variable 'element' is automatically set to NULL if an error occurs.
+ * @note Applicable to all DICOM value representations (VR).
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param element variable in which the reference to (or copy of) the element is stored
* @param searchIntoSub flag indicating whether to search into sequences or not
/** find all elements matching a particular tag and return references to them on a stack.
* This functions always performs a deep search (i.e. searches into sequence of items).
+ * @note Applicable to all DICOM value representations (VR).
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param resultStack stack where references to the elements are stored (added to).
* If no element is found, the stack is not modified (e.g. cleared).
DcmStack &resultStack);
/** find element and get value as a reference to a C string. NB: The string is not copied!
- * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI,
- * UR, UT.
* Since the getString() routine is called internally the resulting string reference represents
* the (possibly multi-valued) value as stored in the dataset, i.e. no normalization is performed.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM,
+ * UC, UI, UR, UT.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored (might be NULL)
* @param searchIntoSub flag indicating whether to search into sequences or not
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a reference to a C string. NB: The string is not copied!
- * Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM, UC, UI,
- * UR, UT.
* Since the getString() routine is called internally the resulting string reference represents
* the (possibly multi-valued) value as stored in the dataset, i.e. no normalization is performed.
* The result variable 'value' is automatically set to NULL and 'length' is set to 0 if an error
* occurs.
* Please note that since the length is returned separately, the string value can contain more
* than one NULL byte.
+ * @note Applicable to the following VRs: AE, AS, CS, DA, DS, DT, IS, LO, LT, PN, SH, ST, TM,
+ * UC, UI, UR, UT.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored (might be NULL)
* @param length length of the string (number of characters without the trailing NULL byte)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a C++ string (only one component).
- * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF,
- * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* Since the getOFString() routine is called internally the resulting string is normalized, i.e.
* leading and/or trailing spaces are removed according to the associated value representation,
* or the element value is converted to a character string (for non-string VRs) - see documentation
* In contrast to the above and below function only the specified component (see parameter 'pos')
* is returned. The result variable 'value' is automatically set to an empty string if an error
* occurs.
+ * @note Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD,
+ * OF, OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a C++ string (all components).
- * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF,
- * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* Since the getOFStringArray() routine is called internally the resulting string is normalized,
* i.e. leading and/or trailing spaces are removed according to the associated value representation
* or the element values are converted to character strings (for non-string VRs) - see documentation
* in the corresponding header file.
* The result variable 'value' is automatically set to an empty string if an error occurs.
+ * @note Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD,
+ * OF, OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param searchIntoSub flag indicating whether to search into sequences or not
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an unsigned 8-bit integer.
- * Applicable to the following VRs: OB.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: OB.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of unsigned 8-bit integers.
- * Applicable to the following VRs: OB.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: OB.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an unsigned 16-bit integer.
- * Applicable to the following VRs: OW, US.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: OW, US.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of unsigned 16-bit integers.
- * Applicable to the following VRs: AT, OW, US.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: AT, OW, US.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a signed 16-bit integer.
- * Applicable to the following VRs: SS.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: SS.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of signed 16-bit integers.
- * Applicable to the following VRs: SS.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: SS.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an unsigned 32-bit integer.
- * Applicable to the following VRs: OL, UL.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: OL, UL.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of unsigned 32-bit integers.
- * Applicable to the following VRs: OL, UL.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: OL, UL.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a signed 32-bit integer.
- * Applicable to the following VRs: IS, SL.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: IS, SL.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of signed 32-bit integers.
- * Applicable to the following VRs: SL.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: SL.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an unsigned 64-bit integer.
- * Applicable to the following VRs: OV, UV.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: OV, UV.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of unsigned 64-bit integers.
- * Applicable to the following VRs: OV, UV.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: OV, UV.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a signed 64-bit integer.
- * Applicable to the following VRs: SV.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: SV.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of signed 64-bit integers.
- * Applicable to the following VRs: SV.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: SV.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a (signed) long integer.
- * Applicable to the following VRs: IS, OL, SL, SS, UL, US.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: IS, OL, SL, SS, UL, US.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a 32-bit floating point.
- * Applicable to the following VRs: FL, OF.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: FL, OF.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of 32-bit floating point values.
- * Applicable to the following VRs: FL, OF.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: FL, OF.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as a 64-bit floating point.
- * Applicable to the following VRs: DS, FD, OD.
* The result variable 'value' is automatically set to zero if an error occurs.
+ * @note Applicable to the following VRs: DS, FD, OD.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the element value is stored
* @param pos index of the value in case of multi-valued elements (0..vm-1)
const OFBool searchIntoSub = OFFalse);
/** find element and get value as an array of 64-bit floating point values.
- * Applicable to the following VRs: FD, OD.
* The result variable 'value' is automatically set to NULL if an error occurs.
+ * @note Applicable to the following VRs: FD, OD.
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param value variable in which the reference to the element value is stored
* @param count stores number of items in the result array (if not NULL)
const OFBool searchIntoSub = OFFalse);
/** looks up and returns a given sequence.
- * Applicable to the following VRs: SQ, (pixelSQ).
* The result variable 'sequence' is automatically set to NULL if an error occurs
* (e.g. if 'seqTagKey' does not refer to a sequence attribute).
+ * @note Applicable to the following VRs: SQ, (pixelSQ).
* @param seqTagKey DICOM tag specifying the sequence attribute to be searched for
* @param sequence variable in which the reference to (or copy of) the sequence is stored
* @param searchIntoSub flag indicating whether to search into sub-sequences or not
* to NULL and returns EC_TagNotFound (specified sequence does not exist) or
* EC_IllegalParameter (specified item does not exist). Only the top-most level of
* the dataset/item is examined (i.e. no deep-search is performed).
- * Applicable to the following VRs: SQ, (pixelSQ).
* Please note that an instance of the DcmPixelItem class cannot be retrieved.
+ * @note Applicable to the following VRs: SQ, (pixelSQ).
* @param seqTagKey DICOM tag specifying the sequence attribute to be searched for
* @param item variable in which the reference to (or copy of) the item is stored
* @param itemNum number of the item to be searched for (0..n-1, -1 for last)
* If either the sequence or the item do not exist, they are created. If necessary,
* multiple empty items are inserted. Only the top-most level of the dataset/item
* is examined (i.e. no deep-search is performed).
- * Applicable to the following VRs: SQ, (pixelSQ).
* Please note that an instance of the DcmPixelItem class cannot be retrieved or
* created.
+ * @note Applicable to the following VRs: SQ, (pixelSQ).
* @param seqTag DICOM tag specifying the sequence attribute to be searched for
* (or to be created)
* @param item variable in which the reference to the sequence item is stored
* of items). Empty elements are also copied. However, if the given tag is not
* found in the current dataset, EC_TagNotFound is returned and the destination
* dataset remains unchanged.
- * Applicable to all DICOM value representations (VR).
+ * @note Applicable to all DICOM value representations (VR).
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param destItem destination dataset to which the copied element is inserted
* @param replaceOld flag indicating whether to replace an existing element or not
const OFBool replaceOld = OFTrue);
/** find element, remove it from the dataset and free the associated memory.
- * Applicable to all DICOM value representations (VR).
+ * @note Applicable to all DICOM value representations (VR).
* @param tagKey DICOM tag specifying the attribute to be searched for
* @param allOccurrences flag indicating whether to delete all occurrences of the
* attribute tag or the first one only (implies 'searchIntoSub' to be true)
const OFBool searchIntoSub = OFFalse);
/** looks up the given sequence in the current dataset and deletes the given item.
- * Applicable to the following VRs: SQ, (pixelSQ).
+ * @note Applicable to the following VRs: SQ, (pixelSQ).
* @param seqTagKey DICOM tag specifying the sequence attribute to be searched for
* @param itemNum number of the item to be deleted (0..n-1, -1 for last)
* @return EC_Normal upon success, an error otherwise.
/* --- putAndInsert functions: put value and insert new element --- */
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF,
- * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
+ * @note Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB,
+ * OD, OF, OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* @param tag DICOM tag specifying the attribute to be created
* @param value string value to be set for the new element (might be empty or NULL). The format
* of the string value is specified by the putString() method of the corresponding VR class.
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF,
- * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* Please note that since the length of the string has to be specified explicitly, the string
* can contain more than one NULL byte.
+ * @note Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB,
+ * OD, OF, OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* @param tag DICOM tag specifying the attribute to be created
* @param value string value to be set for the new element (might be empty or NULL). The format
* of the string value is specified by the putString() method of the corresponding VR class.
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF,
- * OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
+ * @note Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB,
+ * OD, OF, OL, OV, OW, PN, SH, SL, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* @param tag DICOM tag specifying the attribute to be created
* @param value string value to be set for the new element (might be empty). The format of the
* string value is specified by the putOFStringArray() method of the corresponding VR class.
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: OB, ox (polymorph OB/OW or pixel data).
+ * @note Applicable to the following VRs: OB, ox (polymorph OB/OW), px (pixel data).
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element (might be NULL)
* @param count number of values (= bytes in this case) to be copied from 'value'
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: US, xs (US or SS).
+ * @note Applicable to the following VRs: US, xs (US or SS).
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param pos index of the value to be set (0..vm). A value can be appended to
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: AT, OW, US, ox (polymorph OB/OW or pixel data), xs (US or SS).
+ * @note Applicable to the following VRs: AT, OW, US, ox (polymorph OB/OW), px (pixel data),
+ * xs (US or SS).
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element (might be NULL)
* @param count number of values (not bytes!) to be copied from 'value'
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: SS, xs (US or SS).
+ * @note Applicable to the following VRs: SS, xs (US or SS).
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param pos index of the value to be set (0..vm). A value can be appended to
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: SS, xs (US or SS).
+ * @note Applicable to the following VRs: SS, xs (US or SS).
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param count number of values (not bytes!) to be copied from 'value'
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: OL, UL.
+ * @note Applicable to the following VRs: OL, UL.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param pos index of the value to be set (0..vm). A value can be appended to
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: OL, UL.
+ * @note Applicable to the following VRs: OL, UL.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param count number of values (not bytes!) to be copied from 'value'
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: SL.
+ * @note Applicable to the following VRs: SL.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param pos index of the value to be set (0..vm). A value can be appended to
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: SL.
+ * @note Applicable to the following VRs: SL.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param count number of values (not bytes!) to be copied from 'value'
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: FL, OF.
+ * @note Applicable to the following VRs: OV, UV.
+ * @param tag DICOM tag specifying the attribute to be created
+ * @param value value to be set for the new element
+ * @param pos index of the value to be set (0..vm). A value can be appended to
+ * the end of or inserted within the existing value field.
+ * @param replaceOld flag indicating whether to replace an existing element or not
+ * @return EC_Normal upon success, an error code otherwise.
+ */
+ OFCondition putAndInsertUint64(const DcmTag &tag,
+ const Uint64 value,
+ const unsigned long pos = 0,
+ const OFBool replaceOld = OFTrue);
+
+ /** create a new element, put specified value to it and insert the element into the dataset/item.
+ * @note Applicable to the following VRs: OV, UV.
+ * @param tag DICOM tag specifying the attribute to be created
+ * @param value value to be set for the new element
+ * @param count number of values (not bytes!) to be copied from 'value'
+ * @param replaceOld flag indicating whether to replace an existing element or not
+ * @return EC_Normal upon success, an error code otherwise.
+ */
+ OFCondition putAndInsertUint64Array(const DcmTag &tag,
+ const Uint64 *value,
+ const unsigned long count,
+ const OFBool replaceOld = OFTrue);
+
+ /** create a new element, put specified value to it and insert the element into the dataset/item.
+ * @note Applicable to the following VRs: SV.
+ * @param tag DICOM tag specifying the attribute to be created
+ * @param value value to be set for the new element
+ * @param pos index of the value to be set (0..vm). A value can be appended to
+ * the end of or inserted within the existing value field.
+ * @param replaceOld flag indicating whether to replace an existing element or not
+ * @return EC_Normal upon success, an error code otherwise.
+ */
+ OFCondition putAndInsertSint64(const DcmTag &tag,
+ const Sint64 value,
+ const unsigned long pos = 0,
+ const OFBool replaceOld = OFTrue);
+
+ /** create a new element, put specified value to it and insert the element into the dataset/item.
+ * @note Applicable to the following VRs: SV.
+ * @param tag DICOM tag specifying the attribute to be created
+ * @param value value to be set for the new element
+ * @param count number of values (not bytes!) to be copied from 'value'
+ * @param replaceOld flag indicating whether to replace an existing element or not
+ * @return EC_Normal upon success, an error code otherwise.
+ */
+ OFCondition putAndInsertSint64Array(const DcmTag &tag,
+ const Sint64 *value,
+ const unsigned long count,
+ const OFBool replaceOld = OFTrue);
+
+ /** create a new element, put specified value to it and insert the element into the dataset/item.
+ * @note Applicable to the following VRs: FL, OF.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param pos index of the value to be set (0..vm). A value can be appended to
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: FL, OF.
+ * @note Applicable to the following VRs: FL, OF.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param count number of values (not bytes!) to be copied from 'value'
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: DS, FD, OD
+ * @note Applicable to the following VRs: DS, FD, OD
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param pos index of the value to be set (0..vm). A value can be appended to
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: FD, OD.
+ * @note Applicable to the following VRs: FD, OD.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param count number of values (not bytes!) to be copied from 'value'
const OFBool replaceOld = OFTrue);
/** create a new element, put specified value to it and insert the element into the dataset/item.
- * Applicable to the following VRs: AT.
+ * @note Applicable to the following VRs: AT.
* @param tag DICOM tag specifying the attribute to be created
* @param value value to be set for the new element
* @param pos index of the value to be set (0..vm). A value can be appended to
/* --- insertXXX functions: insert new element --- */
/** create a new element (with no value) and insert it into the dataset/item.
- * Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, OB, OD, OF,
- * OL, OV, OW, PN, SH, SL, SQ, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
+ * @note Applicable to the following VRs: AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT,
+ * OB, OD, OF, OL, OV, OW, PN, SH, SL, SQ, SS, ST, SV, TM, UC, UI, UL, UR, US, UT, UV.
* @param tag DICOM tag specifying the attribute to be created
* @param replaceOld flag indicating whether to replace an existing element or not
* @return EC_Normal upon success, an error code otherwise.
* If the sequence does not exist, it is created. If necessary, multiple empty items
* are inserted before the specified item position. Only the top-most level of the
* dataset/item is examined (i.e. no deep-search is performed).
- * Applicable to the following VRs: SQ, (pixelSQ).
* Please note that an instance of the DcmPixelItem class cannot be inserted.
+ * @note Applicable to the following VRs: SQ, (pixelSQ).
* @param seqTag DICOM tag specifying the sequence attribute to be searched for
* (or to be created)
* @param item item to be inserted into the sequence, must not be contained in this
OFBool checkAndUpdateVR(DcmItem &item,
DcmTag &tag);
- /** update the SpecificCharacterSet (0008,0005) element depending on the given
- * parameters. The current value of this element is either replaced or a new
- * element is inserted or the existing element is deleted.
- * @param status error status of previous operations (might also be updated)
- * @param converter character set converter used to convert element values
- */
- void updateSpecificCharacterSet(OFCondition &status,
- const DcmSpecificCharacterSet &converter);
-
/** creates new DICOM element from given attribute tag.
* Helper function used by DICOM parser (friend of this class) and thus
* hidden from the public interface. DcmItem's readSubElement() uses
/*
*
-* Copyright (C) 2017-2022, OFFIS e.V.
+* Copyright (C) 2017-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#define DCJSON_H
#include "dcmtk/config/osconfig.h" // make sure OS specific configuration is included first
-
#include "dcmtk/ofstd/ofdefine.h"
#include "dcmtk/ofstd/ofstring.h"
-
#include "dcmtk/dcmdata/dctagkey.h"
+class OFCondition;
+
/** Class for handling JSON format options.
* Base class to implement custom formatting.
* Purpose:
};
/** A class to create small proxy objects that ease indention handling.
- * Each Indention object only contains a reference to the DcmJsonFormat object
- * that created it and its only purpose is to call the respective methods
- * of that object when one of its overloaded operators is used.
+ * Each Indention object only contains a reference to the DcmJsonFormat
+ * object that created it and its only purpose is to call the respective
+ * methods of that object when one of its overloaded operators is used.
*/
class Indention
{
OFString &value);
/** Constructor
- * @param printMetaInfo parameter that defines if meta information should be written
+ * @param printMetaInfo parameter that defines if meta information should
+ * be written
*/
inline DcmJsonFormat(const OFBool printMetaInfo)
: printMetaheaderInformation(printMetaInfo)
, enableJsonExtension(OFFalse)
, numStringPolicy(NSP_auto)
+ , minBulkDataSize(-1)
+ , bulkDataURIPrefix()
+ , bulkDataDirectory()
{
-
}
/** Virtual destructor, does nothing
*/
virtual OFString space() = 0;
- /** Method to return an indention proxy object for increasing, decreasing or printing indention
+ /** Method to return an indention proxy object for increasing, decreasing or
+ * printing indention
* @return an indention proxy object.
*/
inline Indention indent()
* Override this function to implement bulk data URI output.
* @param tag the tag of the attribute being printed, for letting
* the implementation decide how to handle it.
- * @param uri the resulting URI to output.
+ * @param len the length of the attribute value, in bytes
* @return OFTrue if yes, OFFalse if no.
- * @details
- * <h3>Usage Example:</h3>
- * @code{.cpp}
- * struct BulkDataURIJsonFormat : DcmJsonFormatPretty
- * {
- * CustomJsonFormat(const OFBool printMetaInfo = OFTrue,
- * ... bulkDataURIDatabase)
- * : DcmJsonFormatPretty(printMetaInfo)
- * , TheDatabase(bulkDataURIDatabase)
- * {
- *
- * }
- *
- * virtual OFBool asBulkDataURI(const DcmTagKey& tag, OFString& uri)
- * {
- * ... result = TheDatabase.findBulkDataFor(tag);
- * if (result.found())
- * {
- * uri = result.uri();
- * return OFTrue;
- * }
- * return OFFalse;
- * }
- *
- * ... TheDatabase;
- * }
- * @endcode
*/
- virtual OFBool asBulkDataURI(const DcmTagKey& tag, OFString& uri);
+ virtual OFBool asBulkDataURI(const DcmTagKey& tag, Uint32 len) const;
+
+ /** return path of bulk data directory
+ * @param directory path returned in this parameter
+ */
+ virtual void getBulkDataDirectory(OFString& directory) const;
+
+ /** return the current bulk data URI prefix
+ * @return prefix current bulk data URI prefix returned in this parameter
+ */
+ virtual void getBulkDataURIPrefix(OFString& prefix) const;
/** Print the Prefix which for JSON Values needed
* with indention and newlines as in the format Variable given.
*/
const OFBool printMetaheaderInformation;
+ /** set the minimum size of binary attributes stored as bulk data.
+ * @param min_bulk_size minimum bulk data size in kBytes, negative number for no bulk data
+ */
+ virtual void setMinBulkSize(ssize_t min_bulk_size);
+
+ /** set the prefix for URIs generated for bulk data
+ * @param bulk_uri_prefix URI prefix string
+ */
+ virtual void setBulkURIPrefix(const char *bulk_uri_prefix);
+
+ /** set the directory to which bulk data files should be written
+ * @param bulk_dir directory for bulk data files, must exist and be writable
+ */
+ virtual void setBulkDir(const char *bulk_dir);
+
+ /** write an attribute as BulkDataURI.
+ * @param out output stream
+ * @param tagkey tag key of the attribute
+ * @param len length of the attribute value
+ * @param byteValues pointer to the raw attribute value in little endian byte order
+ * @param extension file name extension
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition writeBulkData(
+ STD_NAMESPACE ostream &out,
+ const DcmTagKey& tagkey,
+ Uint32 len,
+ Uint8 *byteValues,
+ const char *extension = ".bin");
+
+ /** write a binary attribute either as InlineBinary or as BulkDataURI.
+ * @param out output stream
+ * @param tagkey tag key of the attribute
+ * @param len length of the attribute value
+ * @param byteValues pointer to the raw attribute value in little endian byte order
+ * @param extension file name extension
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition writeBinaryAttribute(
+ STD_NAMESPACE ostream &out,
+ const DcmTagKey& tagkey,
+ Uint32 len,
+ Uint8 *byteValues,
+ const char *extension = ".bin");
+
protected:
/** Indent to the specific level.
* @param out output stream to which the indention is written.
* as number or string. Default is NSP_auto.
*/
NumStringPolicy numStringPolicy;
+
+ /** minimum size of binary attributes to be written as bulk data,
+ * in kBytes. A negative value means that no bulk data is written.
+ */
+ ssize_t minBulkDataSize;
+
+ /** prefix for bulk data URIs to be generated. The filename will
+ * be appended to this prefix.
+ */
+ OFString bulkDataURIPrefix;
+
+ /** directory to which files for bulk data will be written.
+ * Must exist and be writable.
+ */
+ OFString bulkDataDirectory;
+
};
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Tingyan Xu, Marco Eichelberg
+ *
+ * Purpose: Class for converting JSON DICOM documents to binary DICOM files
+ *
+ */
+
+#ifndef DCJSONRD_H
+#define DCJSONRD_H
+
+class OFCondition;
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/oftypes.h" /* for OFBool */
+#include "dcmtk/dcmdata/dcdefine.h" /* for DCMTK_DCMDATA_EXPORT */
+#include "dcmtk/dcmdata/dcxfer.h" /* for E_TransferSyntax */
+#include "dcmtk/ofstd/oflist.h" /* for OFList */
+
+#define JSMN_HEADER
+#include "dcmtk/ofstd/ofjsmn.h" /* for JSMN declarations */
+
+typedef jsmn_parser OFJsmnParser;
+typedef jsmntok_t OFJsmnToken;
+typedef OFJsmnToken *OFJsmnTokenPtr;
+
+class DcmFileFormat;
+class DcmElement;
+class DcmTagKey;
+class DcmTag;
+class DcmSequenceOfItems;
+class DcmItem;
+
+
+/** input stream that reads from standard input
+ */
+class DCMTK_DCMDATA_EXPORT DcmJSONReader
+{
+public:
+ /// constructor
+ DcmJSONReader();
+
+ /// destructor
+ virtual ~DcmJSONReader();
+
+ /// delete all internal buffers, but keep policy settings
+ virtual void clear();
+
+ /** read a JSON file and store the content in this object
+ * @param ifname name of the JSON file to be read
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition readJSONFile(const char *ifname);
+
+ /** read a JSON dataset from stdin and store the content in this object
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition readJSONFromStdin();
+
+ /** set the "ignore bulk data URI" policy
+ * @param value new policy, true = ignore bulk data URIs
+ */
+ virtual void setIgnoreBulkdataURIPolicy(OFBool value) { ignoreBulkdataURIPolicy_ = value; }
+
+ /** set the "stop on error" policy
+ * @param value new policy, true = stop when encountering a parse error
+ */
+ virtual void setStopOnErrorPolicy(OFBool value) { stopOnErrorPolicy_ = value; }
+
+ /** set the "ignore meta info" policy
+ * @param value new policy, true = ignore meta info elements in JSON dataset
+ */
+ virtual void setIgnoreMetaInfoPolicy(OFBool value) { ignoreMetaInfoPolicy_ = value; }
+
+ /** set the array handling policy
+ * @param value new policy
+ * - -1: reject arrays with more than one dataset
+ * - 0: store arrays with multiple datasets as a private sequence
+ * - n > 0: select dataset n from the array, ignore all others */
+ virtual void setArrayHandlingPolicy(signed long value) { arrayHandlingPolicy_ = value; }
+
+ /** set the transfer syntax for the dataset
+ * @param value transfer syntax
+ */
+ virtual void setTransferSyntax(E_TransferSyntax value) { xferSyntax_ = value; }
+
+ /** set the transfer syntax for the dataset
+ * @param value transfer syntax
+ */
+ virtual E_TransferSyntax getTransferSyntax() const { return xferSyntax_; }
+
+ /** parse the JSON file with the given filename
+ * @param fileformat DcmFileFormat instance to be populated with the parsed JSON content
+ * @param ifname name of the JSON file to be read
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition readAndConvertJSONFile(
+ DcmFileFormat& fileformat,
+ const char *ifname);
+
+ /** dump the token array produced by the JSMN parser to stderr
+ */
+ virtual OFCondition dumpJSONTokenArray();
+
+ /** check if the given URI is a file URI
+ * @param uri URI to check
+ * @return true if the URI is a file URI
+ */
+ virtual OFBool isFileURI(const OFString& uri) const;
+
+ /** check if the given URI is a http: or https: URI
+ * @param uri URI to check
+ * @return true if the URI is a http: or https: URI
+ */
+ virtual OFBool isHttpURI(const OFString& uri) const;
+
+ /** URL decode the given URI, i.e. replace all instances of '%xx' with the hex number xx
+ * by the corresponding byte.
+ * @param uri URI string, will be modified by this method.
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition urlDecode(OFString& uri) const;
+
+ /** convert a file URI to a file path in the local filesystem
+ * @param uri the file URI to convert
+ * @param filepath the file path is returned in this parameter
+ * @param offset the byte offset within the file is returned in this parameter
+ * @param length the number of bytes to read from the file is returned in this parameter, 0 means 'unlimited'
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition fileURItoPath(const OFString& uri, OFString& filepath, size_t& offset, size_t& length) const;
+
+ /** normalize a file path into an absolute path without symbolic links.
+ * On Windows, the long version of directory and file names will be generated
+ * and converted to uppercase, since the Win32 file API uses case insensitive filenames
+ * @param filepath_in the file path to be normalized
+ * @param filepath_out the normalized file path is returned in this parameter.
+ * This parameter must not reference the same string as filepath_in.
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition normalizePath(const OFString& filepath_in, OFString& filepath_out) const;
+
+ /** add a path from which bulk data files may be read if referenced by a
+ * file BulkdataURI. The path will be normalized before being stored.
+ * All subdirectories of the given directory will also be accepted a valid paths.
+ * @param dirpath the directory path that is acceptable for bulk data
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition addPermittedBulkdataPath(const OFString& dirpath);
+
+ /** check if the given normalized path (which may include a filename)
+ * is in the list of permitted bulk data paths as defined by calls to
+ * addPermittedBulkdataPath().
+ * @param filepath the file path to be checked
+ * @return OFTrue if path is permitted, OFFalse otherwise
+ */
+ virtual OFBool bulkdataPathPermitted(const OFString& filepath) const;
+
+ /** load bulk data from file and insert it into the given element
+ * @param element element into which the value will be inserted
+ * @param filepath path to the bulk data file
+ * @param offset offset in bytes within the file from where to start reading
+ * @param length number of bytes to read from file, 0 for the entire file from the given offset
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition loadBulkdataFile(
+ DcmElement& element,
+ const OFString& filepath,
+ size_t offset,
+ size_t length);
+
+private:
+
+ /// null terminated character string containing the entire JSON dataset
+ char *jsonDataset_;
+
+ /// size of jsonDataset_ in bytes, not including the terminating null byte
+ size_t jsonDatasetLen_;
+
+ /// array of parsed JSON tokens
+ OFJsmnTokenPtr tokenArray_;
+
+ /// number of tokens in tokenArray_
+ int tokenNumber_;
+
+ /// policy for handling bulk data URIs (true = ignore)
+ OFBool ignoreBulkdataURIPolicy_;
+
+ /// policy for error handling (false = ignore)
+ OFBool stopOnErrorPolicy_;
+
+ /// policy for handling meta info elements in the JSON dataset (true = ignore)
+ OFBool ignoreMetaInfoPolicy_;
+
+ /** policy for handling arrays of multiple datasets.
+ * - -1: reject arrays with more than one dataset
+ * - 0: store arrays with multiple datasets as a private sequence
+ * - n > 0: select dataset n from the array, ignore all others
+ */
+ signed long arrayHandlingPolicy_;
+
+ /// transfer syntax of the dataset, default: LittleEndianExplicit
+ E_TransferSyntax xferSyntax_;
+
+ /// list of directories to which file URIs may point
+ OFList<OFString> permittedBulkdataDirs_;
+
+ /** calculate the required number of tokens for the JSON dataset
+ * and allocate the token array accordingly
+ */
+ OFCondition reserveTokens();
+
+ /** parse the JSON dataset that has be read into the buffer
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition parseJSON();
+
+ /// private unimplemented copy constructor
+ DcmJSONReader(const DcmJSONReader&);
+
+ /// private unimplemented copy assignment operator
+ DcmJSONReader& operator=(const DcmJSONReader&);
+
+ /** helper function to retrieve the content of the token.
+ * There is no check on boundaries!
+ * @param value the result string
+ * @param t token pointer
+ */
+ void getTokenContent(
+ OFString& value,
+ OFJsmnTokenPtr t);
+
+ /** create DICOM element using the given tag and VR
+ * @param newElem pointer to newly created DICOM element returned in this parameter
+ * @param dcmTag attribute tag
+ * @param vr the string representation of the VR (if present)
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition createElement(
+ DcmElement *& newElem,
+ DcmTag& dcmTag,
+ const OFString& vr);
+
+ /** extract DICOM tag from the given string
+ * @param keyToken token containing the string representation of the tag in form of "ggggeeee"
+ * @param tagkey stores the extracted DICOM tag
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition extractTag(
+ OFJsmnTokenPtr keyToken,
+ DcmTagKey& tagkey);
+
+ /** helper function processing escaped characters in JSON strings
+ * @param value containing the string. The string will be changed
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition processJSONEscapeCharacters(OFString& value);
+
+ /** parse the dataset part of an XML file containing a DICOM file or a DICOM dataset.
+ * @param dataset dataset stored in this parameter
+ * @param metaheader metaheader stored in this parameter
+ * @param current pointer to current JSMN Token
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition parseDataSet(
+ DcmItem* dataset,
+ DcmItem* metaheader,
+ OFJsmnTokenPtr& current);
+
+ /** parse a DICOM sequence
+ * @param sequence DICOM Sequence
+ * @param current pointer to current token in the tokenArray
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition parseSequence(
+ DcmSequenceOfItems& sequence,
+ OFJsmnTokenPtr& current);
+
+ /** parse a DICOM element that is not a sequence
+ * @param dataset dataset stored in this parameter
+ * @param metaheader metaheader stored in this parameter
+ * @param current pointer to current JSMN Token
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition parseElement(
+ DcmItem* dataset,
+ DcmItem* metaheader,
+ OFJsmnTokenPtr& current);
+
+ /** parse a value array from JSON to DICOM
+ * @param newElem Pointer to element where the value should be stored
+ * @param current pointer to current token in the tokenArray
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition parseElementValueArray(
+ DcmElement*& newElem,
+ OFJsmnTokenPtr& current);
+
+ /** parse a person name (PN value)
+ * @param value string containing the PN DICOM value
+ * @param current pointer to current token in the tokenArray
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition parsePersonName(
+ OFString& value,
+ OFJsmnTokenPtr& current);
+
+ /** store decoded inline binary value in a DICOM element
+ * @param element element into which the value will be inserted
+ * @param data buffer containing the inline binary data
+ * @param length of the buffer
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition storeInlineBinaryValue(
+ DcmElement& element,
+ Uint8 *data,
+ size_t length);
+
+ /** store loaded bulk data value in a DICOM element
+ * @param element element into which the value will be inserted
+ * @param data buffer containing the bulk data
+ * @param length of the buffer
+ * @return EC_Normal upon success, an error code otherwise
+ */
+ virtual OFCondition storeBulkValue(
+ DcmElement& element,
+ Uint8 *data,
+ size_t length);
+
+};
+
+#endif
/*
*
- * Copyright (C) 1994-2021, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/** helper class maintaining an entry in a DcmList double-linked list
*/
-class DCMTK_DCMDATA_EXPORT DcmListNode
+class DCMTK_DCMDATA_EXPORT DcmListNode
{
public:
/** constructor
* @param obj object to be maintained by this list node
*/
- DcmListNode( DcmObject *obj );
+ DcmListNode(DcmObject *obj);
/// destructor
~DcmListNode();
/// return pointer to object maintained by this list node
- inline DcmObject *value() { return objNodeValue; }
+ inline DcmObject *value() { return objNodeValue; }
private:
friend class DcmList;
/// pointer to DcmObject instance maintained by this list entry
DcmObject *objNodeValue;
- /// private undefined copy constructor
+ /// private undefined copy constructor
DcmListNode(const DcmListNode &);
- /// private undefined copy assignment operator
+ /// private undefined copy assignment operator
DcmListNode &operator=(const DcmListNode &);
};
} E_ListPos;
/** double-linked list class that maintains pointers to DcmObject instances.
- * The remove operation does not delete the object pointed to, however,
- * the destructor will delete all elements pointed to
+ * The remove operation does not delete the object pointed to, however, the
+ * destructor will delete all elements the list points to.
*/
-class DCMTK_DCMDATA_EXPORT DcmList
+class DCMTK_DCMDATA_EXPORT DcmList
{
public:
/// constructor
/** insert object at end of list
* @param obj pointer to object
- * @return pointer to object
+ * @return pointer to object, or NULL if object cannot be inserted
*/
- DcmObject *append( DcmObject *obj );
+ DcmObject *append(DcmObject *obj);
/** insert object at start of list
* @param obj pointer to object
- * @return pointer to object
+ * @return pointer to object, or NULL if object cannot be inserted
*/
- DcmObject *prepend( DcmObject *obj );
+ DcmObject *prepend(DcmObject *obj);
/** insert object relative to current position and indicator
* @param obj pointer to object
* @param pos position indicator
- * @return pointer to object
+ * @return pointer to object, or NULL if object cannot be inserted
*/
- DcmObject *insert( DcmObject *obj,
- E_ListPos pos = ELP_next );
+ DcmObject *insert(DcmObject *obj,
+ const E_ListPos pos = ELP_next);
/** remove current entry from list, return element
* @return pointer to removed element, which is not deleted
* @param pos position indicator
* @return pointer to object
*/
- DcmObject *get( E_ListPos pos = ELP_atpos );
+ DcmObject *get(const E_ListPos pos = ELP_atpos);
/** seek within element in list to given position
* (i.e. set current element to given position)
* @param pos position indicator
* @return pointer to new current object
*/
- DcmObject *seek( E_ListPos pos = ELP_next );
+ DcmObject *seek(const E_ListPos pos = ELP_next);
/** seek within element in list to given element index
* (i.e. set current element to given index)
* @param absolute_position position index < card()
* @return pointer to new current object
*/
- DcmObject *seek_to(unsigned long absolute_position);
+ DcmObject *seek_to(const unsigned long absolute_position);
- /** Remove and delete all elements from list. Thus, the
- * elements' memory is also freed by this operation. The list
- * is empty after calling this function.
- */
+ /** remove and delete all elements from list. Thus, the elements' memory
+ * is also freed by this operation. The list is empty after calling this
+ * function.
+ */
void deleteAllElements();
/// return cardinality of list
inline unsigned long card() const { return cardinality; }
/// return true if list is empty, false otherwise
- inline OFBool empty(void) const { return firstNode == NULL; }
+ inline OFBool empty() const { return firstNode == NULL; }
/// return true if current node exists, false otherwise
- inline OFBool valid(void) const { return currentNode != NULL; }
+ inline OFBool valid() const { return currentNode != NULL; }
private:
/// pointer to first node in list
/// pointer to current node in list
DcmListNode *currentNode;
+ /// current position in list.
+ /// The position is maintained in order to avoid O(n) lookup
+ /// when essentially iterating the elements using seek_to().
+ unsigned long currentPosition;
+
/// number of elements in list
unsigned long cardinality;
-
- /// private undefined copy constructor
+
+ /// private undefined copy constructor
DcmList &operator=(const DcmList &);
/** private undefined copy assignment operator
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_GrpLenEncoding groupLength = EGL_noChange,
const Uint32 maxReadLength = DCM_MaxReadLength);
+ /** access the file preamble after reading a DICOM file.
+ * @return pointer to a 132-byte array containing the DICOM file preamble
+ * (i.e. the unused first 128 bytes of a DICOM file) and the magic word
+ * ("DICM"). If no DICOM fileformat was loaded, array will be zeroed.
+ */
+ virtual const char *getPreamble() const;
private:
/*
*
- * Copyright (C) 2003-2024, OFFIS e.V.
+ * Copyright (C) 2003-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofcond.h"
#include "dcmtk/ofstd/oftypes.h"
+#include "dcmtk/ofstd/ofdiag.h"
#include "dcmtk/dcmdata/dcxfer.h"
#ifdef __ibmxl__
typedef struct _xmlDoc xmlDoc;
typedef xmlDoc *xmlDocPtr;
+// MacOS 15.5 defines some Clang specific pragmas in libxml header files.
+// Suppress warnings caused by these pragmas when compiling with GCC.
+#include DCMTK_DIAGNOSTIC_PUSH
+#include DCMTK_DIAGNOSTIC_IGNORE_CLANG_PRAGMAS_ON_GCC
#include <libxml/xmlstring.h>
+#include DCMTK_DIAGNOSTIC_POP
class DcmElement;
class DcmItem;
/// in write function: pointer to current pixel sequence
DcmPixelSequence * pixelSeqForWrite;
+
/** check if this element should be written unencapsulated, even though an
* encapsulated transfer syntax is used. In other words, this checks if
* this pixel data element is on the main level on the dataset or not.
virtual OFCondition getDecompressedColorModel(
DcmItem *dataset,
OFString &decompressedColorModel);
+
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return effective value of BitsAllocated, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
};
#endif
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
virtual OFCondition writeXML(STD_NAMESPACE ostream &out,
const size_t flags = 0);
+ /** write object in JSON format to a stream
+ * @param out output stream to which the JSON document is written
+ * @param format used to format and customize the output
+ * @return status, EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition writeJson(STD_NAMESPACE ostream &out,
+ DcmJsonFormat &format);
+
/** special write method for creation of digital signatures
* @param outStream DICOM output stream
* @param oxfer output transfer syntax
/*
*
- * Copyright (C) 2002-2011, OFFIS e.V.
+ * Copyright (C) 2002-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_TransferSyntax oldRepType,
const E_TransferSyntax newRepType) const;
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded with this codec.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
/** determine color model of the decompressed image
* @param fromParam representation parameter of current compressed
* representation, may be NULL
/*
*
- * Copyright (C) 2002-2020, OFFIS e.V.
+ * Copyright (C) 2002-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_TransferSyntax oldRepType,
const E_TransferSyntax newRepType) const;
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded with this codec.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
/** determine color model of the decompressed image
* @param fromParam representation parameter of current compressed
* representation, may be NULL
/*
*
- * Copyright (C) 2011-2017, OFFIS e.V.
+ * Copyright (C) 2011-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/** A class for managing and converting between different DICOM character sets.
* The conversion relies on the OFCharacterEncoding class, which again relies
- * on an underlying character encoding library (e.g. libiconv or ICU).
+ * on an underlying character encoding library (e.g. oficonv or libiconv).
* @note Please note that a current limitation is that only a single value is
* allowed for the destination character set (i.e. no code extensions). Of
* course, for the source character set, also multiple values are supported.
/** destructor
*/
- ~DcmSpecificCharacterSet();
+ virtual ~DcmSpecificCharacterSet();
/** clear the internal state. This also forgets about the currently
* selected character sets, so selectCharacterSet() has to be called again
* before a string can be converted with convertString().
*/
- void clear();
+ virtual void clear();
/** query whether selectCharacterSet() has successfully been called for this
* object, i.e.\ whether convertString() may be called.
* @return OFTrue if selectCharacterSet() was successfully called before,
* OFFalse if not (or clear() has been called in the meantime).
*/
+ virtual
#ifdef HAVE_CXX11
explicit
#endif
* @return OFTrue if selectCharacterSet() must be called before using
* convertString(), OFFalse if it has already been called.
*/
- OFBool operator!() const;
+ virtual OFBool operator!() const;
/** get currently selected source DICOM character set(s). Please note that
* the returned string can contain multiple values (defined terms separated
* @return currently selected source DICOM character set(s) or an empty
* string if none is selected (identical to ASCII, which is the default)
*/
- const OFString &getSourceCharacterSet() const;
+ virtual const OFString &getSourceCharacterSet() const;
/** get currently selected destination DICOM character set. Please note
* that the returned string, which contains a defined term, is always
* @return currently selected destination DICOM character set or an empty
* string if none is selected (identical to ASCII, which is the default)
*/
- const OFString &getDestinationCharacterSet() const;
+ virtual const OFString &getDestinationCharacterSet() const;
/** get currently selected destination encoding, i.e.\ the name of the
* character set as used by the underlying character encoding library for
* @return currently selected destination encoding or an empty string if
* none is selected
*/
- const OFString &getDestinationEncoding() const;
+ virtual const OFString &getDestinationEncoding() const;
/** @copydoc OFCharacterEncoding::getConversionFlags()
*/
- unsigned getConversionFlags() const;
+ virtual unsigned getConversionFlags() const;
/** @copydoc OFCharacterEncoding::setConversionFlags()
*/
- OFCondition setConversionFlags(const unsigned flags);
+ virtual OFCondition setConversionFlags(const unsigned flags);
/** select DICOM character sets for the input and output string, between
* which subsequent calls of convertString() convert. The defined terms
* default value is "ISO_IR 192" (Unicode in UTF-8).
* @return status, EC_Normal if successful, an error code otherwise
*/
- OFCondition selectCharacterSet(const OFString &fromCharset,
- const OFString &toCharset = "ISO_IR 192");
+ virtual OFCondition selectCharacterSet(const OFString &fromCharset,
+ const OFString &toCharset = "ISO_IR 192");
/** select DICOM character sets for the input and output string, between
* which subsequent calls of convertString() convert. The source
* value is "ISO_IR 192" (Unicode in UTF-8).
* @return status, EC_Normal if successful, an error code otherwise
*/
- OFCondition selectCharacterSet(DcmItem &dataset,
- const OFString &toCharset = "ISO_IR 192");
+ virtual OFCondition selectCharacterSet(DcmItem &dataset,
+ const OFString &toCharset = "ISO_IR 192");
/** convert the given string from the selected source character set(s) to
* the selected destination character set. That means selectCharacterSet()
* has to be called prior to this method.
+ * @note The conversion code does not perform a thorough validation of the
+ * string. For example, characters that are permitted in the source
+ * character set but forbidden in DICOM (such as byte positions 0x80-0x9F
+ * in ISO_IR 100) may be converted without warning or error.
* @param fromString input string to be converted (using the currently
* selected source character set)
* @param toString reference to variable where the converted string
* always regarded as delimiters (see DICOM PS 3.5).
* @return status, EC_Normal if successful, an error code otherwise
*/
- OFCondition convertString(const OFString &fromString,
- OFString &toString,
- const OFString &delimiters = "");
+ virtual OFCondition convertString(const OFString &fromString,
+ OFString &toString,
+ const OFString &delimiters = "");
/** convert the given string from the selected source character set(s) to
* the selected destination character set. That means selectCharacterSet()
* has to be called prior to this method. Since the length of the input
* string has to be specified explicitly, the string can contain more than
* one NULL byte.
+ * @note The conversion code does not perform a thorough validation of the
+ * string. For example, characters that are permitted in the source
+ * character set but forbidden in DICOM (such as byte positions 0x80-0x9F
+ * in ISO_IR 100) may be converted without warning or error.
* @param fromString input string to be converted (using the currently
* selected character set)
* @param fromLength length of the input string (number of bytes without
* always regarded as delimiters (see DICOM PS 3.5).
* @return status, EC_Normal if successful, an error code otherwise
*/
- OFCondition convertString(const char *fromString,
- const size_t fromLength,
- OFString &toString,
- const OFString &delimiters = "");
+ virtual OFCondition convertString(const char *fromString,
+ const size_t fromLength,
+ OFString &toString,
+ const OFString &delimiters = "");
// --- static helper functions ---
* output string
* @return status, EC_Normal if successful, an error code otherwise
*/
- OFCondition determineDestinationEncoding(const OFString &toCharset);
+ virtual OFCondition determineDestinationEncoding(const OFString &toCharset);
/** select a particular DICOM character set without code extensions for
* subsequent conversions. The corresponding DICOM defined term for the
* 'SourceCharacterSet'.
* @return status, EC_Normal if successful, an error code otherwise
*/
- OFCondition selectCharacterSetWithoutCodeExtensions();
+ virtual OFCondition selectCharacterSetWithoutCodeExtensions();
/** select a particular DICOM character set with code extensions for
* subsequent conversions. The corresponding DICOM defined terms for the
* already been determined by the calling method.
* @return status, EC_Normal if successful, an error code otherwise
*/
- OFCondition selectCharacterSetWithCodeExtensions(const unsigned long sourceVM);
+ virtual OFCondition selectCharacterSetWithCodeExtensions(const unsigned long sourceVM);
+
+ /** convert the given string from the selected source character set (without
+ * code extensions) to the selected destination character set
+ * @param fromString input string to be converted
+ * @param fromLength length of the input string (in bytes)
+ * @param toString reference to variable where to store the converted
+ * string
+ * @param delimiters string of characters regarded as delimiters
+ * @return status, EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition convertStringWithoutCodeExtensions(const char *fromString,
+ const size_t fromLength,
+ OFString &toString,
+ const OFString &delimiters);
+ /** convert the given string from the selected source character set(s) to
+ * the selected destination character set. This method supports code
+ * extension techniques according to ISO 2022 for the input string.
+ * @param fromString input string to be converted
+ * @param fromLength length of the input string (in bytes)
+ * @param toString reference to variable where to store the
+ * converted string
+ * @param delimiters string of characters regarded as delimiters
+ * @param hasEscapeChar flag indicating wether the input string contains
+ * one or more escape characters (ESC)
+ * @return status, EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition convertStringWithCodeExtensions(const char *fromString,
+ const size_t fromLength,
+ OFString &toString,
+ const OFString &delimiters,
+ const OFBool hasEscapeChar);
/** check whether the given string contains at least one escape character
* (ESC), because it is used for code extension techniques like ISO 2022
* @param strLength length of the input string
* @return OFTrue if an escape character has been found, OFFalse otherwise
*/
- OFBool checkForEscapeCharacter(const char *strValue,
- const size_t strLength) const;
+ virtual OFBool checkForEscapeCharacter(const char *strValue,
+ const size_t strLength) const;
/** convert given string to octal format, i.e.\ all non-ASCII and control
* characters are converted to their octal representation. The total
* @param strLength length of the input string
* @return resulting string in octal format
*/
- OFString convertToLengthLimitedOctalString(const char *strValue,
- const size_t strLength) const;
+ virtual OFString convertToLengthLimitedOctalString(const char *strValue,
+ const size_t strLength) const;
private:
/*
*
- * Copyright (C) 1994-2021, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcdefine.h"
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
/* needed e.g. on Solaris for definition of size_t */
#include <sys/types.h>
-#endif
END_EXTERN_C
/*
EWM_dataset = 1,
/// write as fileformat and update required information (e.g. SOP Class/Instance UID)
EWM_updateMeta = 2,
- /// write as fileformat and create new meta header (do not retain existing information)
+ /// write as fileformat and create new meta header (do not retain existing information except SOP Class/Instance UID)
EWM_createNewMeta = 3,
/// write as fileformat but don't update the meta header (please be careful!)
EWM_dontUpdateMeta = 4
/** @name print() flags.
* These flags can be combined and passed to the print() methods.
*/
- //@{
+ ///@{
/// shorten long tag values (e.g. long texts, pixel data)
static const size_t PF_shortenLongTagValues;
/// use ANSI escape codes for output
static const size_t PF_useANSIEscapeCodes;
- //@}
+ ///@}
/** @name writeXML() flags.
* These flags can be combined and passed to the writeXML() methods.
*/
- //@{
+ ///@{
/// add document type definition (DTD). DCMTK-specific format only.
static const size_t XF_addDocumentType;
/// The default is to use the DCMTK-specific format.
static const size_t XF_useNativeModel;
- //@}
+ ///@}
/** @name convertCharacterSet() flags.
* These flags can be combined and passed to the convertCharacterSet() methods.
*/
- //@{
+ ///@{
/// try to approximate characters that cannot be represented through similar
/// looking characters. See DcmSpecificCharacterSet::getTransliterationMode().
/// See DcmSpecificCharacterSet::getDiscardIllegalSequenceMode().
static const size_t CF_discardIllegal;
- //@}
+ ///@}
};
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#define UID_EncapsulatedUncompressedExplicitVRLittleEndianTransferSyntax "1.2.840.10008.1.2.1.98"
/// Deflated Explicit VR Little Endian
#define UID_DeflatedExplicitVRLittleEndianTransferSyntax "1.2.840.10008.1.2.1.99"
+/// Deflated Image Frame Compression
+#define UID_DeflatedImageFrameCompressionTransferSyntax "1.2.840.10008.1.2.8.1"
/** JPEG Baseline (Process 1): Default Transfer Syntax
* for Lossy JPEG 8 Bit Image Compression
*/
#define UID_ElectrooculogramWaveformStorage "1.2.840.10008.5.1.4.1.1.9.7.3"
#define UID_SleepElectroencephalogramWaveformStorage "1.2.840.10008.5.1.4.1.1.9.7.4"
#define UID_BodyPositionWaveformStorage "1.2.840.10008.5.1.4.1.1.9.8.1"
+#define UID_WaveformPresentationStateStorage "1.2.840.10008.5.1.4.1.1.9.100.1"
+#define UID_WaveformAcquisitionPresentationStateStorage "1.2.840.10008.5.1.4.1.1.9.100.2"
#define UID_RETIRED_StandaloneModalityLUTStorage "1.2.840.10008.5.1.4.1.1.10"
#define UID_RETIRED_StandaloneVOILUTStorage "1.2.840.10008.5.1.4.1.1.11"
#define UID_GrayscaleSoftcopyPresentationStateStorage "1.2.840.10008.5.1.4.1.1.11.1"
#define UID_DICONDE_EddyCurrentMultiframeImageStorage "1.2.840.10008.5.1.4.1.1.601.2"
#define UID_DICONDE_ThermographyImageStorage "1.2.840.10008.5.1.4.1.1.601.3"
#define UID_DICONDE_ThermographyMultiFrameImageStorage "1.2.840.10008.5.1.4.1.1.601.4"
+#define UID_DICONDE_UltrasoundWaveformStorage "1.2.840.10008.5.1.4.1.1.601.5"
// Query/Retrieve
#define UID_FINDPatientRootQueryRetrieveInformationModel "1.2.840.10008.5.1.4.1.2.1.1"
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition getOFString(OFString &stringVal,
- const unsigned long pos,
- OFBool normalize = OFTrue);
+ const unsigned long pos,
+ OFBool normalize = OFTrue);
// ensure inherited overloads of matches take part in overload resolution
using DcmByteString::matches;
/*
*
- * Copyright (C) 1994-2021, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const char *pixelFileName,
size_t *pixelCounter);
+ /**
+ * compares two binary values for equality.
+ * This function compares the binary data pointed to by `myValue` and `rhsValue`
+ * for equality up to the specified length `valLength`. See compare() method
+ * for more details.
+ *
+ * @param myValue pointer to the first value to compare.
+ * @param rhsValue pointer to the second value to compare.
+ * @param valLength the number of bytes to compare.
+ * @return an integer less than, equal to, or greater than zero if the first value
+ * is found to be less than, equal to, or greater than the second value.
+ */
+ virtual int compareValues(const void* myValue,
+ const void* rhsValue,
+ const unsigned long valLength) const;
+
private:
/** this flag is used during write operations and indicates that compact() should be
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
EXS_RLELossless = 23,
/// Deflated Explicit VR Little Endian
EXS_DeflatedLittleEndianExplicit = 24,
+ /// Deflated Image Frame Compression
+ EXS_DeflatedImageFrameCompression = 25,
/// JPEG-LS (lossless)
- EXS_JPEGLSLossless = 25,
+ EXS_JPEGLSLossless = 26,
/// JPEG-LS (lossless or near-lossless mode)
- EXS_JPEGLSLossy = 26,
+ EXS_JPEGLSLossy = 27,
/// JPEG 2000 (lossless)
- EXS_JPEG2000LosslessOnly = 27,
+ EXS_JPEG2000LosslessOnly = 28,
/// JPEG 2000 (lossless or lossy)
- EXS_JPEG2000 = 28,
+ EXS_JPEG2000 = 29,
/// JPEG 2000 part 2 multi-component extensions (lossless)
- EXS_JPEG2000MulticomponentLosslessOnly = 29,
+ EXS_JPEG2000MulticomponentLosslessOnly = 30,
/// JPEG 2000 part 2 multi-component extensions (lossless or lossy)
- EXS_JPEG2000Multicomponent = 30,
+ EXS_JPEG2000Multicomponent = 31,
/// JPIP Referenced
- EXS_JPIPReferenced = 31,
+ EXS_JPIPReferenced = 32,
/// JPIP Referenced Deflate
- EXS_JPIPReferencedDeflate = 32,
+ EXS_JPIPReferencedDeflate = 33,
/// MPEG2 Main Profile at Main Level
- EXS_MPEG2MainProfileAtMainLevel = 33,
+ EXS_MPEG2MainProfileAtMainLevel = 34,
/// Fragmentable MPEG2 Main Profile / Main Level
- EXS_FragmentableMPEG2MainProfileMainLevel = 34,
+ EXS_FragmentableMPEG2MainProfileMainLevel = 35,
/// MPEG2 Main Profile at High Level
- EXS_MPEG2MainProfileAtHighLevel = 35,
+ EXS_MPEG2MainProfileAtHighLevel = 36,
/// Fragmentable MPEG2 Main Profile / High Level
- EXS_FragmentableMPEG2MainProfileHighLevel = 36,
+ EXS_FragmentableMPEG2MainProfileHighLevel = 37,
/// MPEG4 High Profile / Level 4.1
- EXS_MPEG4HighProfileLevel4_1 = 37,
+ EXS_MPEG4HighProfileLevel4_1 = 38,
/// Fragmentable MPEG4 High Profile / Level 4.1
- EXS_FragmentableMPEG4HighProfileLevel4_1 = 38,
+ EXS_FragmentableMPEG4HighProfileLevel4_1 = 39,
/// MPEG4 BD-compatible High Profile / Level 4.1
- EXS_MPEG4BDcompatibleHighProfileLevel4_1 = 39,
+ EXS_MPEG4BDcompatibleHighProfileLevel4_1 = 40,
/// Fragmentable MPEG4 BD-compatible High Profile / Level 4.1
- EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1 = 40,
+ EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1 = 41,
/// MPEG4 High Profile / Level 4.2 For 2D Video
- EXS_MPEG4HighProfileLevel4_2_For2DVideo = 41,
+ EXS_MPEG4HighProfileLevel4_2_For2DVideo = 42,
/// Fragmentable MPEG4 High Profile / Level 4.2 For 2D Video
- EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo = 42,
+ EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo = 43,
/// MPEG4 High Profile / Level 4.2 For 3D Video
- EXS_MPEG4HighProfileLevel4_2_For3DVideo = 43,
+ EXS_MPEG4HighProfileLevel4_2_For3DVideo = 44,
/// Fragmentable MPEG4 Stereo High Profile / Level 4.2
- EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo = 44,
+ EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo = 45,
/// MPEG4 Stereo High Profile / Level 4.2
- EXS_MPEG4StereoHighProfileLevel4_2 = 45,
+ EXS_MPEG4StereoHighProfileLevel4_2 = 46,
/// Fragmentable HEVC/H.265 Main Profile / Level 5.1
- EXS_FragmentableMPEG4StereoHighProfileLevel4_2 = 46,
+ EXS_FragmentableMPEG4StereoHighProfileLevel4_2 = 47,
/// HEVC/H.265 Main Profile / Level 5.1
- EXS_HEVCMainProfileLevel5_1 = 47,
+ EXS_HEVCMainProfileLevel5_1 = 48,
/// HEVC/H.265 Main 10 Profile / Level 5.1
- EXS_HEVCMain10ProfileLevel5_1 = 48,
+ EXS_HEVCMain10ProfileLevel5_1 = 49,
/// JPEG XL Lossless
- EXS_JPEGXLLossless = 49,
+ EXS_JPEGXLLossless = 50,
/// JPEG XL JPEG Recompression
- EXS_JPEGXLJPEGRecompression = 50,
+ EXS_JPEGXLJPEGRecompression = 51,
/// JPEG XL
- EXS_JPEGXL = 51,
+ EXS_JPEGXL = 52,
/// High-Throughput JPEG 2000 Image Compression (Lossless Only)
- EXS_HighThroughputJPEG2000LosslessOnly = 52,
+ EXS_HighThroughputJPEG2000LosslessOnly = 53,
/// High-Throughput JPEG 2000 with RPCL Options Image Compression (Lossless Only)
- EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly = 53,
+ EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly = 54,
/// High-Throughput JPEG 2000 Image Compression
- EXS_HighThroughputJPEG2000 = 54,
+ EXS_HighThroughputJPEG2000 = 55,
/// JPIP HTJ2K Referenced
- EXS_JPIPHTJ2KReferenced = 55,
+ EXS_JPIPHTJ2KReferenced = 56,
/// JPIP HTJ2K Referenced Deflate
- EXS_JPIPHTJ2KReferencedDeflate = 56,
+ EXS_JPIPHTJ2KReferencedDeflate = 57,
/// Private GE Little Endian Implicit with big endian pixel data
- EXS_PrivateGE_LEI_WithBigEndianPixelData = 57
+ EXS_PrivateGE_LEI_WithBigEndianPixelData = 58
} E_TransferSyntax;
return isPixelDataLosslessCompressed() || isDatasetCompressed();
}
+ /** get DICOMweb MIME type for pixel data in this transfer syntax
+ * @return DICOMweb MIME type for pixel data in this transfer syntax
+ */
+ inline const char *getMIMEType() const
+ {
+ return mimeType;
+ }
+
+ /** get suggested filename extension to use when storing pixel data
+ * of this transfer syntax as bulk data for use with DICOMweb
+ * @return suggested filename extension
+ */
+ inline const char *getFilenameExtension() const
+ {
+ return filenameExtension;
+ }
+
/** get the number of bytes needed to describe the tag, length, VR and any
* reserved fields for this transfer syntax when encoding the specified VR.
* @param evr value representation to be encoded in this transfer syntax
/// validity of the transfer syntax definition (e.g. standard, retired, private)
E_XferValidity xferValidity;
+
+ /// MIME type used for this transfer syntax in DICOMweb
+ const char *mimeType;
+
+ /// file name extension for storing bulk data in this transfer syntax
+ const char *filenameExtension;
+
};
/** global constant describing the byte order on the machine the application
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/** Destructor, frees plugin memory
*/
- ~Image2Dcm();
+ virtual ~Image2Dcm();
/** Start the conversion. Needs a fully configured input plugin
* and a fully configured output plugin to operate. Returns
I2DImgSource *inputPlug,
size_t frameNumber);
+ /** Adjust byte order of the pixel data to local byte order for the OW VR.
+ * @param numberOfFrames - [in] The number of frames to be written
+ * @return EC_Normal, if successful, error otherwise
+ */
+ virtual OFCondition adjustByteOrder(size_t numberOfFrames);
+
/** Update the offset table in the case of an encapsulated image
* @return EC_Normal if offset table could be updated, error code otherwise
*/
/** Reads pixel data and corresponding attributes like rows etc. from image
* file and inserts them into dataset.
* @param imageSource - [in] The input plugin that actually reads the pixel data
+ * @param outPlug - [in] The output plugin for specific SOP class output
* @param numberOfFrames - [in] The number of frames to be written
* @param dset - [out] The dataset to export the pixel data attributes to
* @param outputTS - [out] The proposed transfex syntax of the dataset
*/
OFCondition readAndInsertPixelDataFirstFrame(
I2DImgSource* imageSource,
+ I2DOutputPlug *outPlug,
size_t numberOfFrames,
DcmDataset* dset,
E_TransferSyntax& outputTS,
/*
*
- * Copyright (C) 2007-2022, OFFIS e.V.
+ * Copyright (C) 2007-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* @param imageHeight - [out] The height of the image
* @param samplesPerPixel - [out] Number of components per pixel
* @param bitsPerSample - [out] Number of bits per pixel component
+ * @param colorModel - [out] color model of the JPEG bitstream
* @return EC_Normal, if successful, error otherwise
*/
OFCondition getSOFImageParameters(const JPEGFileMapEntry& entry,
Uint16& imageWidth,
Uint16& imageHeight,
Uint16& samplesPerPixel,
- Uint16& bitsPerSample);
+ Uint16& bitsPerSample,
+ OFString& colorModel);
/** Get image parameters as found at given SOF marker of the JPEG image.
* Used for JPEG-LS codec.
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/oflog/oflog.h"
#include "dcmtk/ofstd/oflist.h"
#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/dcmdata/dcxfer.h"
#include "dcmtk/dcmdata/libi2d/i2define.h"
extern DCMTK_I2D_EXPORT OFLogger DCM_dcmdataLibi2dLogger;
*/
virtual OFBool supportsMultiframe() const = 0;
+ /** checks if the output SOP class permits the given combination of
+ * transfer syntax and photometric interpretation
+ * @param photometricInterpretation - [in] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return true if combination permitted, false otherwise
+ */
+ virtual OFBool colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const = 0;
+
+ /** change the photometric interpretation to the next best permitted one, for lenient mode
+ * @param photometricInterpretation - [in/out] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return EC_Normal if a "compatible" replacement exists, an error code otherwise
+ */
+ virtual OFCondition updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const = 0;
+
/** Add multiframe specific attributes
* @param targetDataset pointer to DICOM dataset, must not be NULL
* @param numberOfFrames number of frames in this dataset
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFBool supportsMultiframe() const;
+ /** checks if the output SOP class permits the given combination of
+ * transfer syntax and photometric interpretation
+ * @param photometricInterpretation - [in] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return true if combination permitted, false otherwise
+ */
+ virtual OFBool colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
+ /** change the photometric interpretation to the next best permitted one, for lenient mode
+ * @param photometricInterpretation - [in/out] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return EC_Normal if a "compatible" replacement exists, an error code otherwise
+ */
+ virtual OFCondition updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
/** Add multiframe specific attributes
* @param targetDataset pointer to DICOM dataset, must not be NULL
* @param numberOfFrames number of frames in this dataset
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFBool supportsMultiframe() const;
+ /** checks if the output SOP class permits the given combination of
+ * transfer syntax and photometric interpretation
+ * @param photometricInterpretation - [in] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return true if combination permitted, false otherwise
+ */
+ virtual OFBool colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
+ /** change the photometric interpretation to the next best permitted one, for lenient mode
+ * @param photometricInterpretation - [in/out] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return EC_Normal if a "compatible" replacement exists, an error code otherwise
+ */
+ virtual OFCondition updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
/** Add multiframe specific attributes
* @param targetDataset pointer to DICOM dataset, must not be NULL
* @param numberOfFrames number of frames in this dataset
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFBool supportsMultiframe() const;
+ /** checks if the output SOP class permits the given combination of
+ * transfer syntax and photometric interpretation
+ * @param photometricInterpretation - [in] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return true if combination permitted, false otherwise
+ */
+ virtual OFBool colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
+ /** change the photometric interpretation to the next best permitted one, for lenient mode
+ * @param photometricInterpretation - [in/out] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return EC_Normal if a "compatible" replacement exists, an error code otherwise
+ */
+ virtual OFCondition updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
/** Add multiframe specific attributes
* @param targetDataset pointer to DICOM dataset, must not be NULL
* @param numberOfFrames number of frames in this dataset
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFBool supportsMultiframe() const;
+ /** checks if the output SOP class permits the given combination of
+ * transfer syntax and photometric interpretation
+ * @param photometricInterpretation - [in] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return true if combination permitted, false otherwise
+ */
+ virtual OFBool colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
+ /** change the photometric interpretation to the next best permitted one, for lenient mode
+ * @param photometricInterpretation - [in/out] photometric interpretation
+ * @param outputTS - [in] output transfer syntax
+ * @return EC_Normal if a "compatible" replacement exists, an error code otherwise
+ */
+ virtual OFCondition updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const;
+
/** Add multiframe specific attributes
* @param targetDataset pointer to DICOM dataset, must not be NULL
* @param numberOfFrames number of frames in this dataset
../include/dcmtk/dcmdata/dcmxml/dcxmldf.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
- ../../ofstd/include/dcmtk/ofstd/ofexport.h \
- ../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/oftypes.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../../ofstd/include/dcmtk/ofstd/ofstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstream.h \
- ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
- ../../ofstd/include/dcmtk/ofstd/diag/push.def \
- ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
- ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
- ../../oflog/include/dcmtk/oflog/oflog.h \
- ../../oflog/include/dcmtk/oflog/logger.h \
- ../../oflog/include/dcmtk/oflog/config.h \
- ../../oflog/include/dcmtk/oflog/config/defines.h \
- ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
- ../../oflog/include/dcmtk/oflog/loglevel.h \
- ../../ofstd/include/dcmtk/ofstd/ofvector.h \
- ../../oflog/include/dcmtk/oflog/tstring.h \
- ../../oflog/include/dcmtk/oflog/tchar.h \
- ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
- ../../oflog/include/dcmtk/oflog/appender.h \
- ../../ofstd/include/dcmtk/ofstd/ofmem.h \
- ../../ofstd/include/dcmtk/ofstd/ofutil.h \
- ../../ofstd/include/dcmtk/ofstd/oftraits.h \
- ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
- ../../oflog/include/dcmtk/oflog/layout.h \
- ../../oflog/include/dcmtk/oflog/streams.h \
- ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
- ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
- ../../oflog/include/dcmtk/oflog/spi/filter.h \
- ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
- ../../oflog/include/dcmtk/oflog/spi/logfact.h \
- ../../oflog/include/dcmtk/oflog/logmacro.h \
- ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
- ../../oflog/include/dcmtk/oflog/tracelog.h \
- ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../include/dcmtk/dcmdata/dcsequen.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
- ../../ofstd/include/dcmtk/ofstd/oflimits.h \
- ../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \
- ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dctag.h \
- ../include/dcmtk/dcmdata/dctagkey.h \
- ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
- ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
- ../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h \
- ../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcofsetl.h \
- ../include/dcmtk/dcmdata/dcpixel.h ../include/dcmtk/dcmdata/dcvrpobw.h \
- ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcpxitem.h \
- ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcfilefo.h \
- ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcmetinf.h \
- ../include/dcmtk/dcmdata/dcswap.h
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h
/*
*
- * Copyright (C) 2003-2024, OFFIS e.V.
+ * Copyright (C) 2003-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcmetinf.h"
#include "dcmtk/dcmdata/dcswap.h"
+#include "dcmtk/ofstd/ofdiag.h"
+
+// MacOS 15.5 defines some Clang specific pragmas in libxml header files.
+// Suppress warnings caused by these pragmas when compiling with GCC.
+#include DCMTK_DIAGNOSTIC_PUSH
+#include DCMTK_DIAGNOSTIC_IGNORE_CLANG_PRAGMAS_ON_GCC
#include <libxml/parser.h>
+#include DCMTK_DIAGNOSTIC_POP
// This function is also used in dcmsr, try to stay in sync!
-#if defined(HAVE_VSNPRINTF) && defined(HAVE_PROTOTYPE_VSNPRINTF)
extern "C" void xml2dcm_errorFunction(void * ctx, const char *msg, ...)
{
// Classic C requires us to declare variables at the beginning of the function.
OFString &buffer = *OFstatic_cast(OFString*, ctx);
-#else
-extern "C" void xml2dcm_errorFunction(void * /* ctx */, const char *msg, ...)
-{
-#endif
if (!DCM_dcmdataLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
return;
-#if defined(HAVE_VSNPRINTF) && defined(HAVE_PROTOTYPE_VSNPRINTF)
// libxml calls us multiple times for one line of log output which would
// result in garbled output. To avoid this, we buffer the output in a local
// string in the caller which we get through our 'ctx' parameter. Then, we
pos = buffer.find('\n');
}
-#else
- // No vsnprint, but at least vfprintf. Output the messages directly to stderr.
- va_list ap;
- va_start(ap, msg);
-#ifdef HAVE_PROTOTYPE_STD__VFPRINTF
- std::vfprintf(stderr, msg, ap);
-#else
- vfprintf(stderr, msg, ap);
-#endif
- va_end(ap);
-#endif
}
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmdata/libi2d/i2define.h \
- ../include/dcmtk/dcmdata/libi2d/i2dimgs.h \
../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/libi2d/i2define.h \
+ ../include/dcmtk/dcmdata/libi2d/i2dimgs.h \
../include/dcmtk/dcmdata/dcpixel.h ../include/dcmtk/dcmdata/dcvrpobw.h \
../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \
../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcuid.h \
../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcpath.h \
+ ../include/dcmtk/dcmdata/dcswap.h \
../include/dcmtk/dcmdata/dcmxml/xml2dcm.h \
../include/dcmtk/dcmdata/dcmxml/dcxmldf.h
i2dbmps.o: i2dbmps.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
+ ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../include/dcmtk/dcmdata/libi2d/i2define.h \
../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
../../ofstd/include/dcmtk/ofstd/offile.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcdefine.h \
- ../include/dcmtk/dcmdata/dcobject.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
- ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \
../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
+ ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../include/dcmtk/dcmdata/libi2d/i2define.h \
../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dctagkey.h \
- ../include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdatset.h \
../include/dcmtk/dcmdata/dcitem.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcobject.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
- ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \
../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcstack.h \
../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h
i2dplop.o: i2dplop.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
+ ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../include/dcmtk/dcmdata/libi2d/i2define.h \
../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dctagkey.h \
- ../include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../include/dcmtk/dcmdata/dcuid.h \
../../ofstd/include/dcmtk/ofstd/ofdatime.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcobject.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
- ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \
../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcstack.h \
../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h
i2dplsc.o: i2dplsc.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
+ ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../include/dcmtk/dcmdata/libi2d/i2define.h \
../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dctagkey.h \
- ../include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdatset.h \
../include/dcmtk/dcmdata/dcitem.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcobject.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
- ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \
../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcstack.h \
../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h
i2dplvlp.o: i2dplvlp.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../include/dcmtk/dcmdata/dcxfer.h ../include/dcmtk/dcmdata/dctypes.h \
+ ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../include/dcmtk/dcmdata/libi2d/i2define.h \
../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dctagkey.h \
- ../include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdatset.h \
../include/dcmtk/dcmdata/dcitem.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcobject.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
- ../include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dcerror.h \
../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dcstack.h \
../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcpcache.h
/*
*
- * Copyright (C) 2007-2024, OFFIS e.V.
+ * Copyright (C) 2007-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/libi2d/i2d.h"
#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/dcmdata/dcpxitem.h"
-#include "dcmtk/dcmdata/dcfilefo.h" /* for DcmFileFormat */
-#include "dcmtk/dcmdata/dcdeftag.h" /* for DCM_ defines */
-#include "dcmtk/dcmdata/dcuid.h" /* for SITE_SERIES_UID_ROOT */
-#include "dcmtk/dcmdata/dcpixseq.h" /* for DcmPixelSequence */
-#include "dcmtk/dcmdata/dcpath.h" /* for override keys */
-#include "dcmtk/dcmdata/dcmxml/xml2dcm.h" /* for DcmXMLParseHelper */
+#include "dcmtk/dcmdata/dcfilefo.h" /* for DcmFileFormat */
+#include "dcmtk/dcmdata/dcdeftag.h" /* for DCM_ defines */
+#include "dcmtk/dcmdata/dcuid.h" /* for SITE_SERIES_UID_ROOT */
+#include "dcmtk/dcmdata/dcpixseq.h" /* for DcmPixelSequence */
+#include "dcmtk/dcmdata/dcpath.h" /* for override keys */
+#include "dcmtk/dcmdata/dcswap.h" /* for swapIfNecessary() */
+#include "dcmtk/dcmdata/dcmxml/xml2dcm.h" /* for DcmXMLParseHelper */
OFLogger DCM_dcmdataLibi2dLogger = OFLog::getLogger("dcmtk.dcmdata.libi2d");
// Read and insert pixel data
m_compressionRatio = 1.0;
- cond = readAndInsertPixelDataFirstFrame(inputPlug, numberOfFrames, tempDataset.get(), proposedTS, m_compressionRatio);
+ cond = readAndInsertPixelDataFirstFrame(inputPlug, outPlug, numberOfFrames, tempDataset.get(), proposedTS, m_compressionRatio);
if (cond.bad())
{
return cond;
OFCondition Image2Dcm::readAndInsertPixelDataFirstFrame(
I2DImgSource* imgSource,
+ I2DOutputPlug *outPlug,
size_t numberOfFrames,
DcmDataset* dset,
E_TransferSyntax& outputTS,
if (cond.bad())
return cond;
+ if (! outPlug->colorModelPermitted(m_photometricInterpretation, outputTS))
+ {
+ OFString old_photometricInterpretation = m_photometricInterpretation;
+ cond = outPlug->updateColorModel(m_photometricInterpretation, outputTS);
+ DcmXfer xf(outputTS);
+ if (cond.good())
+ {
+ DCMDATA_LIBI2D_WARN("Image2Dcm: photometric interpretation '" << old_photometricInterpretation << "' not permitted for the selected SOP class in '" << xf.getXferName() << "' transfer syntax, using '" << m_photometricInterpretation << "' instead");
+ }
+ else
+ {
+ DCMDATA_LIBI2D_ERROR("Image2Dcm: photometric interpretation '" << old_photometricInterpretation << "' not permitted for the selected SOP class in '" << xf.getXferName() << "' transfer syntax");
+ return cond;
+ }
+ }
+
cond = dset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, m_photometricInterpretation);
if (cond.bad())
return cond;
if (m_offsetTable) result = m_offsetTable->createOffsetTable(m_offsetList);
return result;
}
+
+
+OFCondition Image2Dcm::adjustByteOrder(size_t numberOfFrames)
+{
+ if (m_output_buffer)
+ {
+ // unencapsulated pixel data, byte swapping may be necessary
+ if (m_bitsAllocated < 9)
+ {
+ size_t bufSize = m_frameLength * numberOfFrames;
+ if (bufSize & 1) ++bufSize;
+ if (bufSize > 1)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, m_output_buffer, OFstatic_cast(Uint32, bufSize), sizeof(Uint16));
+ }
+ }
+ }
+ return EC_Normal;
+}
/*
*
- * Copyright (C) 2007-2024, OFFIS e.V.
+ * Copyright (C) 2007-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// Extract width, height, samples per pixel, bits per sample
Uint16 width, height, spp, bps;
- cond = getSOFImageParameters(**entry, width, height, spp, bps);
+ cond = getSOFImageParameters(**entry, width, height, spp, bps, photoMetrInt);
if (cond.bad())
{
closeFile();
cols = width;
samplesPerPixel = spp;
bitsStored = bps;
- bitsAlloc = bps;
- // When BitsStored = 12, we use BitsAllocated = 16
- if (bitsAlloc == 12)
- {
- bitsAlloc = 16;
- }
+ // bitsAlloc is always the next largest multiple of 8
+ if (bitsStored <= 8)
+ bitsAlloc = 8;
+ else bitsAlloc = 16;
// HighBit is always BitsStored - 1.
- highBit = bitsStored;
- highBit--;
+ highBit = bitsStored -1;
- if (samplesPerPixel == 1)
- photoMetrInt = "MONOCHROME2";
- else if (samplesPerPixel == 3)
+ if ((samplesPerPixel != 1) && (samplesPerPixel != 3))
{
- if (m_isJPEGLS)
- photoMetrInt = "RGB";
- else
- photoMetrInt = "YBR_FULL_422";
- }
- else
return makeOFCondition(OFM_dcmdata, 18, OF_error, "For JPEG data, Samples per Pixel must be 1 or 3");
+ }
+
// Planar Configuration and Pixel Representation is always 0 for JPEG data
planConf = 0;
pixelRepr = 0;
Uint32 tLength = 0;
char* tPixelData = NULL;
- cond = extractRawJPEGStream(tPixelData, tLength);
+ cond = extractRawJPEGStream(tPixelData, tLength);
if (cond.bad())
{
closeFile();
Uint16& imageWidth,
Uint16& imageHeight,
Uint16& samplesPerPixel,
- Uint16& bitsPerSample)
+ Uint16& bitsPerSample,
+ OFString& colorModel)
{
DCMDATA_LIBI2D_DEBUG("I2DJpegSource: Examining JPEG SOF image parameters");
if (!isSOFMarker(entry.marker, m_isJPEGLS))
if (length != OFstatic_cast(unsigned int, 8 + num_components * 3))
return makeOFCondition(OFM_dcmdata, 18, OF_error, "Bogus SOF marker length");
+ if (samplesPerPixel == 1)
+ {
+ colorModel = "MONOCHROME2";
+ }
+ else if (samplesPerPixel == 3)
+ {
+ if (m_isJPEGLS)
+ {
+ colorModel = "RGB";
+ }
+ else
+ {
+ // This is a lossy color JPEG file.
+ // Read component IDs and sampling factors
+ Uint8 i1=0, i2=0, i3=0, ss1=0, ss2=0, ss3=0, n=0;
+ result = read1Byte(i1);
+ if (result != EOF) result = read1Byte(ss1);
+ if (result != EOF) result = read1Byte(n);
+ if (result != EOF) result = read1Byte(i2);
+ if (result != EOF) result = read1Byte(ss2);
+ if (result != EOF) result = read1Byte(n);
+ if (result != EOF) result = read1Byte(i3);
+ if (result != EOF) result = read1Byte(ss3);
+ if (result == EOF)
+ return makeOFCondition(OFM_dcmdata, 18, OF_error, "Premature EOF in JPEG file");
+ if (ss1 == 0x11 && ss2 == 0x11 && ss3 == 0x11)
+ {
+ DCMDATA_LIBI2D_DEBUG("I2DJpegSource: No subsampling");
+ if (i1 == 'R' && i2 == 'G' && i3 == 'B')
+ {
+ // an Adobe RGB JPEG
+ colorModel = "RGB";
+ }
+ else
+ {
+ // DICOM CP 1654 requires "YBR_FULL_422" to be used for lossy JPEG
+ // independent from the actual subsampling in use. Therefore, we use
+ // "YBR_FULL_422" and not "YBR_FULL". See DICOM Part 5, Table 8.2.1-1.
+ colorModel = "YBR_FULL_422";
+ }
+ }
+ else if (ss1 == 0x21 && ss2 == 0x11 && ss3 == 0x11)
+ {
+ DCMDATA_LIBI2D_DEBUG("I2DJpegSource: 4:2:2 subsampling");
+ colorModel = "YBR_FULL_422";
+ }
+ else if (ss1 == 0x22 && ss2 == 0x11 && ss3 == 0x11)
+ {
+ DCMDATA_LIBI2D_DEBUG("I2DJpegSource: non-standard 4:2:0 subsampling");
+ DCMDATA_LIBI2D_WARN("JPEG file contains non-standard 4:2:0 subsampling");
+ colorModel = "YBR_FULL_422";
+ }
+ else if (ss1 == 0x41 && ss2 == 0x11 && ss3 == 0x11)
+ {
+ DCMDATA_LIBI2D_DEBUG("I2DJpegSource: non-standard 4:1:1 subsampling");
+ DCMDATA_LIBI2D_WARN("JPEG file contains non-standard 4:1:1 subsampling");
+ colorModel = "YBR_FULL_422";
+ }
+ else
+ {
+ DCMDATA_LIBI2D_DEBUG("I2DJpegSource: non-standard subsampling: "
+ << OFstatic_cast(unsigned int, ss1 >> 4) << "/" << OFstatic_cast(unsigned int, ss1 & 15) << ", "
+ << OFstatic_cast(unsigned int, ss2 >> 4) << "/" << OFstatic_cast(unsigned int, ss2 & 15) << ", "
+ << OFstatic_cast(unsigned int, ss3 >> 4) << "/" << OFstatic_cast(unsigned int, ss3 & 15));
+ DCMDATA_LIBI2D_WARN("JPEG file contains non-standard subsampling");
+ colorModel = "YBR_FULL_422";
+ }
+ }
+ }
return EC_Normal;
}
+
OFCondition I2DJpegSource::getSOSImageParameters(const JPEGFileMapEntry& entry,
Uint8& nearLossless)
{
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+OFBool I2DOutputPlugNewSC::colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const
+{
+ if (photometricInterpretation == "MONOCHROME2") return OFTrue;
+
+ // DICOM part 3, section A.8.5.4:
+ // Photometric Interpretation (0028,0004) shall be RGB for uncompressed or lossless compressed Transfer Syntaxes that do not have defined color space transformations,
+ // YBR_ICT for irreversible JPEG 2000 Transfer Syntaxes,
+ // YBR_RCT for reversible JPEG 2000 Transfer Syntaxes,
+ // YBR_PARTIAL_420 for MPEG2, MPEG-4 AVC/H.264, HEVC/H.265 Transfer Syntaxes and
+ // YBR_FULL_422 for JPEG lossy compressed Transfer Syntaxes and
+ // YBR_FULL or RGB for RLE Transfer Syntaxes
+ switch(outputTS)
+ {
+ case EXS_JPEG2000:
+ case EXS_JPEG2000Multicomponent:
+ case EXS_HighThroughputJPEG2000:
+ return (photometricInterpretation == "YBR_ICT");
+ /* break; */
+ case EXS_JPEG2000LosslessOnly:
+ case EXS_JPEG2000MulticomponentLosslessOnly:
+ case EXS_HighThroughputJPEG2000LosslessOnly:
+ case EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly:
+ return (photometricInterpretation == "YBR_RCT");
+ /* break; */
+ case EXS_MPEG2MainProfileAtMainLevel:
+ case EXS_FragmentableMPEG2MainProfileMainLevel:
+ case EXS_MPEG2MainProfileAtHighLevel:
+ case EXS_FragmentableMPEG2MainProfileHighLevel:
+ case EXS_MPEG4HighProfileLevel4_1:
+ case EXS_FragmentableMPEG4HighProfileLevel4_1:
+ case EXS_MPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_MPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_MPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_MPEG4StereoHighProfileLevel4_2:
+ case EXS_FragmentableMPEG4StereoHighProfileLevel4_2:
+ case EXS_HEVCMainProfileLevel5_1:
+ case EXS_HEVCMain10ProfileLevel5_1:
+ return (photometricInterpretation == "YBR_PARTIAL_420");
+ /* break; */
+ case EXS_JPEGProcess1:
+ case EXS_JPEGProcess2_4:
+ case EXS_JPEGProcess3_5:
+ case EXS_JPEGProcess6_8:
+ case EXS_JPEGProcess7_9:
+ case EXS_JPEGProcess10_12:
+ case EXS_JPEGProcess11_13:
+ case EXS_JPEGProcess16_18:
+ case EXS_JPEGProcess17_19:
+ case EXS_JPEGProcess20_22:
+ case EXS_JPEGProcess21_23:
+ case EXS_JPEGProcess24_26:
+ case EXS_JPEGProcess25_27:
+ return (photometricInterpretation == "YBR_FULL_422");
+ /* break; */
+ case EXS_RLELossless:
+ return ((photometricInterpretation == "YBR_FULL") || (photometricInterpretation == "RGB"));
+ /* break; */
+ case EXS_JPEGXLLossless:
+ case EXS_JPEGXLJPEGRecompression:
+ case EXS_JPEGXL:
+ // DICOM part 3 does not (yet) specify any requirements for this IOD and JPEG-XL.
+ return OFTrue;
+ /* break; */
+ default:
+ return (photometricInterpretation == "RGB");
+ /* break; */
+ }
+}
+
+
+OFCondition I2DOutputPlugNewSC::updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const
+{
+ if (photometricInterpretation == "MONOCHROME2") return EC_Normal;
+ switch(outputTS)
+ {
+ case EXS_JPEG2000:
+ case EXS_JPEG2000Multicomponent:
+ case EXS_HighThroughputJPEG2000:
+ if (photometricInterpretation == "YBR_ICT") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEG2000LosslessOnly:
+ case EXS_JPEG2000MulticomponentLosslessOnly:
+ case EXS_HighThroughputJPEG2000LosslessOnly:
+ case EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly:
+ if (photometricInterpretation == "YBR_RCT") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_MPEG2MainProfileAtMainLevel:
+ case EXS_FragmentableMPEG2MainProfileMainLevel:
+ case EXS_MPEG2MainProfileAtHighLevel:
+ case EXS_FragmentableMPEG2MainProfileHighLevel:
+ case EXS_MPEG4HighProfileLevel4_1:
+ case EXS_FragmentableMPEG4HighProfileLevel4_1:
+ case EXS_MPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_MPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_MPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_MPEG4StereoHighProfileLevel4_2:
+ case EXS_FragmentableMPEG4StereoHighProfileLevel4_2:
+ case EXS_HEVCMainProfileLevel5_1:
+ case EXS_HEVCMain10ProfileLevel5_1:
+ if (photometricInterpretation == "YBR_PARTIAL_420") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEGProcess1:
+ case EXS_JPEGProcess2_4:
+ case EXS_JPEGProcess3_5:
+ case EXS_JPEGProcess6_8:
+ case EXS_JPEGProcess7_9:
+ case EXS_JPEGProcess10_12:
+ case EXS_JPEGProcess11_13:
+ case EXS_JPEGProcess16_18:
+ case EXS_JPEGProcess17_19:
+ case EXS_JPEGProcess20_22:
+ case EXS_JPEGProcess21_23:
+ case EXS_JPEGProcess24_26:
+ case EXS_JPEGProcess25_27:
+ // silently replace "YBR_FULL" by "YBR_FULL_422". Most JPEG codecs won't mind.
+ if (photometricInterpretation == "YBR_FULL")
+ {
+ photometricInterpretation = "YBR_FULL_422";
+ return EC_Normal;
+ }
+ else if (photometricInterpretation == "YBR_FULL_422") return EC_Normal;
+ else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_RLELossless:
+ if ((photometricInterpretation == "YBR_FULL") || (photometricInterpretation == "RGB")) return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEGXLLossless:
+ case EXS_JPEGXLJPEGRecompression:
+ case EXS_JPEGXL:
+ // DICOM part 3 does not (yet) specify any requirements for this IOD and JPEG-XL.
+ return EC_Normal;
+ /* break; */
+ default:
+ if (photometricInterpretation == "RGB") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ }
+}
+
+
OFCondition I2DOutputPlugNewSC::insertMultiFrameAttributes(
DcmDataset* targetDataset,
size_t numberOfFrames) const
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+OFBool I2DOutputPlugOphthalmicPhotography::colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const
+{
+ if (photometricInterpretation == "MONOCHROME2") return OFTrue;
+
+ // DICOM part 3, C.8.17.2.1.3:
+ // When Samples per Pixel (0028,0002) is greater than 1,
+ // Photometric Interpretation (0028,0004) shall be RGB for uncompressed or lossless compressed Transfer Syntaxes that do not have defined color space transformations,
+ // YBR_ICT for irreversible JPEG 2000 Transfer Syntaxes,
+ // YBR_RCT for reversible JPEG 2000 Transfer Syntaxes,
+ // YBR_PARTIAL_420 for MPEG2, MPEG-4 AVC/H.264, HEVC/H.265 Transfer Syntaxes and
+ // YBR_FULL_422 for JPEG lossy compressed Transfer Syntaxes.
+ // Note that YBR_FULL is explicitly not permitted for RLE in this SOP class.
+ switch(outputTS)
+ {
+ case EXS_JPEG2000:
+ case EXS_JPEG2000Multicomponent:
+ case EXS_HighThroughputJPEG2000:
+ return (photometricInterpretation == "YBR_ICT");
+ /* break; */
+ case EXS_JPEG2000LosslessOnly:
+ case EXS_JPEG2000MulticomponentLosslessOnly:
+ case EXS_HighThroughputJPEG2000LosslessOnly:
+ case EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly:
+ return (photometricInterpretation == "YBR_RCT");
+ /* break; */
+ case EXS_MPEG2MainProfileAtMainLevel:
+ case EXS_FragmentableMPEG2MainProfileMainLevel:
+ case EXS_MPEG2MainProfileAtHighLevel:
+ case EXS_FragmentableMPEG2MainProfileHighLevel:
+ case EXS_MPEG4HighProfileLevel4_1:
+ case EXS_FragmentableMPEG4HighProfileLevel4_1:
+ case EXS_MPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_MPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_MPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_MPEG4StereoHighProfileLevel4_2:
+ case EXS_FragmentableMPEG4StereoHighProfileLevel4_2:
+ case EXS_HEVCMainProfileLevel5_1:
+ case EXS_HEVCMain10ProfileLevel5_1:
+ return (photometricInterpretation == "YBR_PARTIAL_420");
+ /* break; */
+ case EXS_JPEGProcess1:
+ case EXS_JPEGProcess2_4:
+ case EXS_JPEGProcess3_5:
+ case EXS_JPEGProcess6_8:
+ case EXS_JPEGProcess7_9:
+ case EXS_JPEGProcess10_12:
+ case EXS_JPEGProcess11_13:
+ case EXS_JPEGProcess16_18:
+ case EXS_JPEGProcess17_19:
+ case EXS_JPEGProcess20_22:
+ case EXS_JPEGProcess21_23:
+ case EXS_JPEGProcess24_26:
+ case EXS_JPEGProcess25_27:
+ return (photometricInterpretation == "YBR_FULL_422");
+ /* break; */
+ case EXS_JPEGXLLossless:
+ case EXS_JPEGXLJPEGRecompression:
+ case EXS_JPEGXL:
+ // DICOM part 3 does not (yet) specify any requirements for this IOD and JPEG-XL.
+ return OFTrue;
+ /* break; */
+ default:
+ return (photometricInterpretation == "RGB");
+ /* break; */
+ }
+}
+
+
+OFCondition I2DOutputPlugOphthalmicPhotography::updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const
+{
+ if (photometricInterpretation == "MONOCHROME2") return EC_Normal;
+ switch(outputTS)
+ {
+ case EXS_JPEG2000:
+ case EXS_JPEG2000Multicomponent:
+ case EXS_HighThroughputJPEG2000:
+ if (photometricInterpretation == "YBR_ICT") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEG2000LosslessOnly:
+ case EXS_JPEG2000MulticomponentLosslessOnly:
+ case EXS_HighThroughputJPEG2000LosslessOnly:
+ case EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly:
+ if (photometricInterpretation == "YBR_RCT") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_MPEG2MainProfileAtMainLevel:
+ case EXS_FragmentableMPEG2MainProfileMainLevel:
+ case EXS_MPEG2MainProfileAtHighLevel:
+ case EXS_FragmentableMPEG2MainProfileHighLevel:
+ case EXS_MPEG4HighProfileLevel4_1:
+ case EXS_FragmentableMPEG4HighProfileLevel4_1:
+ case EXS_MPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_MPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_MPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_MPEG4StereoHighProfileLevel4_2:
+ case EXS_FragmentableMPEG4StereoHighProfileLevel4_2:
+ case EXS_HEVCMainProfileLevel5_1:
+ case EXS_HEVCMain10ProfileLevel5_1:
+ if (photometricInterpretation == "YBR_PARTIAL_420") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEGProcess1:
+ case EXS_JPEGProcess2_4:
+ case EXS_JPEGProcess3_5:
+ case EXS_JPEGProcess6_8:
+ case EXS_JPEGProcess7_9:
+ case EXS_JPEGProcess10_12:
+ case EXS_JPEGProcess11_13:
+ case EXS_JPEGProcess16_18:
+ case EXS_JPEGProcess17_19:
+ case EXS_JPEGProcess20_22:
+ case EXS_JPEGProcess21_23:
+ case EXS_JPEGProcess24_26:
+ case EXS_JPEGProcess25_27:
+ // silently replace "YBR_FULL" by "YBR_FULL_422". Most JPEG codecs won't mind.
+ if (photometricInterpretation == "YBR_FULL")
+ {
+ photometricInterpretation = "YBR_FULL_422";
+ return EC_Normal;
+ }
+ else if (photometricInterpretation == "YBR_FULL_422") return EC_Normal;
+ else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEGXLLossless:
+ case EXS_JPEGXLJPEGRecompression:
+ case EXS_JPEGXL:
+ // DICOM part 3 does not (yet) specify any requirements for this IOD and JPEG-XL.
+ return EC_Normal;
+ /* break; */
+ default:
+ if (photometricInterpretation == "RGB") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ }
+}
+
+
OFCondition I2DOutputPlugOphthalmicPhotography::insertMultiFrameAttributes(
DcmDataset* targetDataset,
size_t numberOfFrames) const
/*
*
- * Copyright (C) 2001-2021, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+OFBool I2DOutputPlugSC::colorModelPermitted(const OFString& /* photometricInterpretation */, E_TransferSyntax /* outputTS */) const
+{
+ // in secondary capture, no restrictions exist
+ return OFTrue;
+}
+
+
+OFCondition I2DOutputPlugSC::updateColorModel(OFString& /* photometricInterpretation */, E_TransferSyntax /* outputTS */) const
+{
+ return EC_Normal;
+}
+
+
OFCondition I2DOutputPlugSC::insertMultiFrameAttributes(
DcmDataset* /* targetDataset */,
size_t /* numberOfFrames */) const
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+OFBool I2DOutputPlugVLP::colorModelPermitted(const OFString& photometricInterpretation, E_TransferSyntax outputTS) const
+{
+ if (photometricInterpretation == "MONOCHROME2") return OFTrue;
+
+ // DICOM part 3, C.8.12.1.1.1:
+ // Photometric Interpretation (0028,0004) shall be RGB for uncompressed or lossless compressed Transfer Syntaxes that do not have defined color space transformations,
+ // YBR_ICT for irreversible JPEG 2000 Transfer Syntaxes,
+ // YBR_RCT for reversible JPEG 2000 Transfer Syntaxes,
+ // YBR_PARTIAL_420 for MPEG2, MPEG-4 AVC/H.264, HEVC/H.265 Transfer Syntaxes and
+ // YBR_FULL_422 for JPEG lossy compressed Transfer Syntaxes.
+ // Note that YBR_FULL is explicitly not permitted for RLE in this SOP class.
+
+ switch(outputTS)
+ {
+ case EXS_JPEG2000:
+ case EXS_JPEG2000Multicomponent:
+ case EXS_HighThroughputJPEG2000:
+ return (photometricInterpretation == "YBR_ICT");
+ /* break; */
+ case EXS_JPEG2000LosslessOnly:
+ case EXS_JPEG2000MulticomponentLosslessOnly:
+ case EXS_HighThroughputJPEG2000LosslessOnly:
+ case EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly:
+ return (photometricInterpretation == "YBR_RCT");
+ /* break; */
+ case EXS_MPEG2MainProfileAtMainLevel:
+ case EXS_FragmentableMPEG2MainProfileMainLevel:
+ case EXS_MPEG2MainProfileAtHighLevel:
+ case EXS_FragmentableMPEG2MainProfileHighLevel:
+ case EXS_MPEG4HighProfileLevel4_1:
+ case EXS_FragmentableMPEG4HighProfileLevel4_1:
+ case EXS_MPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_MPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_MPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_MPEG4StereoHighProfileLevel4_2:
+ case EXS_FragmentableMPEG4StereoHighProfileLevel4_2:
+ case EXS_HEVCMainProfileLevel5_1:
+ case EXS_HEVCMain10ProfileLevel5_1:
+ return (photometricInterpretation == "YBR_PARTIAL_420");
+ /* break; */
+ case EXS_JPEGProcess1:
+ case EXS_JPEGProcess2_4:
+ case EXS_JPEGProcess3_5:
+ case EXS_JPEGProcess6_8:
+ case EXS_JPEGProcess7_9:
+ case EXS_JPEGProcess10_12:
+ case EXS_JPEGProcess11_13:
+ case EXS_JPEGProcess16_18:
+ case EXS_JPEGProcess17_19:
+ case EXS_JPEGProcess20_22:
+ case EXS_JPEGProcess21_23:
+ case EXS_JPEGProcess24_26:
+ case EXS_JPEGProcess25_27:
+ return (photometricInterpretation == "YBR_FULL_422");
+ /* break; */
+ case EXS_JPEGXLLossless:
+ case EXS_JPEGXLJPEGRecompression:
+ case EXS_JPEGXL:
+ // DICOM part 3 does not (yet) specify any requirements for this IOD and JPEG-XL.
+ return OFTrue;
+ /* break; */
+ default:
+ return (photometricInterpretation == "RGB");
+ /* break; */
+ }
+}
+
+
+OFCondition I2DOutputPlugVLP::updateColorModel(OFString& photometricInterpretation, E_TransferSyntax outputTS) const
+{
+ if (photometricInterpretation == "MONOCHROME2") return EC_Normal;
+ switch(outputTS)
+ {
+ case EXS_JPEG2000:
+ case EXS_JPEG2000Multicomponent:
+ case EXS_HighThroughputJPEG2000:
+ if (photometricInterpretation == "YBR_ICT") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEG2000LosslessOnly:
+ case EXS_JPEG2000MulticomponentLosslessOnly:
+ case EXS_HighThroughputJPEG2000LosslessOnly:
+ case EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly:
+ if (photometricInterpretation == "YBR_RCT") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_MPEG2MainProfileAtMainLevel:
+ case EXS_FragmentableMPEG2MainProfileMainLevel:
+ case EXS_MPEG2MainProfileAtHighLevel:
+ case EXS_FragmentableMPEG2MainProfileHighLevel:
+ case EXS_MPEG4HighProfileLevel4_1:
+ case EXS_FragmentableMPEG4HighProfileLevel4_1:
+ case EXS_MPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1:
+ case EXS_MPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo:
+ case EXS_MPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo:
+ case EXS_MPEG4StereoHighProfileLevel4_2:
+ case EXS_FragmentableMPEG4StereoHighProfileLevel4_2:
+ case EXS_HEVCMainProfileLevel5_1:
+ case EXS_HEVCMain10ProfileLevel5_1:
+ if (photometricInterpretation == "YBR_PARTIAL_420") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEGProcess1:
+ case EXS_JPEGProcess2_4:
+ case EXS_JPEGProcess3_5:
+ case EXS_JPEGProcess6_8:
+ case EXS_JPEGProcess7_9:
+ case EXS_JPEGProcess10_12:
+ case EXS_JPEGProcess11_13:
+ case EXS_JPEGProcess16_18:
+ case EXS_JPEGProcess17_19:
+ case EXS_JPEGProcess20_22:
+ case EXS_JPEGProcess21_23:
+ case EXS_JPEGProcess24_26:
+ case EXS_JPEGProcess25_27:
+ // silently replace "YBR_FULL" by "YBR_FULL_422". Most JPEG codecs won't mind.
+ if (photometricInterpretation == "YBR_FULL")
+ {
+ photometricInterpretation = "YBR_FULL_422";
+ return EC_Normal;
+ }
+ else if (photometricInterpretation == "YBR_FULL_422") return EC_Normal;
+ else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ case EXS_JPEGXLLossless:
+ case EXS_JPEGXLJPEGRecompression:
+ case EXS_JPEGXL:
+ // DICOM part 3 does not (yet) specify any requirements for this IOD and JPEG-XL.
+ return EC_Normal;
+ /* break; */
+ default:
+ if (photometricInterpretation == "RGB") return EC_Normal; else return makeOFCondition(OFM_dcmdata, 18, OF_error, "Unsupported color model");
+ /* break; */
+ }
+}
+
+
OFCondition I2DOutputPlugVLP::insertMultiFrameAttributes(
DcmDataset* /* targetDataset */,
size_t /* numberOfFrames */) const
dcdict.cc
dcdictbi.cc
dcdirrec.cc
+ dcdocdec.cc
dcelem.cc
dcencdoc.cc
dcerror.cc
dcistrmz.cc
dcitem.cc
dcjson.cc
+ dcjsonrd.cc
dclist.cc
dcmatch.cc
dcmetinf.cc
../include/dcmtk/dcmdata/dcvrol.h ../include/dcmtk/dcmdata/dcvrov.h \
../include/dcmtk/dcmdata/cmdlnarg.h ../include/dcmtk/dcmdata/dcspchrs.h \
../../ofstd/include/dcmtk/ofstd/ofchrenc.h
+dcdocdec.o: dcdocdec.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmdata/dcdocdec.h ../include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../include/dcmtk/dcmdata/dcfilefo.h ../include/dcmtk/dcmdata/dcsequen.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
+ ../include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
+ ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
+ ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdeftag.h \
+ ../include/dcmtk/dcmdata/dcuid.h
dcelem.o: dcelem.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
- ../../ofstd/include/dcmtk/ofstd/diag/pop.def
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofsha256.h \
+ ../include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../include/dcmtk/dcmdata/dcerror.h
+dcjsonrd.o: dcjsonrd.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmdata/dcjsonrd.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../include/dcmtk/dcmdata/dcdefine.h ../include/dcmtk/dcmdata/dcxfer.h \
+ ../include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofjsmn.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcfilefo.h \
+ ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \
+ ../include/dcmtk/dcmdata/dcobject.h ../include/dcmtk/dcmdata/dctag.h \
+ ../include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
+ ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
+ ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcmetinf.h \
+ ../include/dcmtk/dcmdata/dcdeftag.h ../include/dcmtk/dcmdata/dcswap.h \
+ ../include/dcmtk/dcmdata/dcvrov.h ../include/dcmtk/dcmdata/dcvruv.h
dclist.o: dclist.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/ofstream.h \
../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
../include/dcmtk/dcmdata/dclist.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
../../ofstd/include/dcmtk/ofstd/ofstring.h \
../../ofstd/include/dcmtk/ofstd/ofrand.h \
+ ../../ofstd/include/dcmtk/ofstd/ofsha256.h \
../include/dcmtk/dcmdata/dcpixseq.h ../include/dcmtk/dcmdata/dcsequen.h \
../../ofstd/include/dcmtk/ofstd/offile.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcpxitem.h \
../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcitem.h \
- ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdeftag.h
+ ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcdeftag.h \
+ ../include/dcmtk/dcmdata/dcjson.h
dcpxitem.o: dcpxitem.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/ofstream.h \
../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmath.h \
../include/dcmtk/dcmdata/dcvrod.h ../include/dcmtk/dcmdata/dcvrfd.h \
../include/dcmtk/dcmdata/dcelem.h ../include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmath.h \
../include/dcmtk/dcmdata/dcjson.h ../include/dcmtk/dcmdata/dctagkey.h \
../include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
dcvrut.o dcvrur.o dcvruc.o dctypes.o dcpcache.o dcddirif.o dcistrma.o \
dcistrmb.o dcistrmf.o dcistrms.o dcistrmz.o dcostrma.o dcostrmb.o \
dcostrmf.o dcostrms.o dcostrmz.o dcwcache.o dcpath.o vrscan.o vrscanl.o \
- dcfilter.o dcmatch.o dcjson.o
+ dcfilter.o dcmatch.o dcjson.o dcjsonrd.o dcdocdec.o
support_objs = mkdeftag.o mkdictbi.o
support_progs = mkdeftag mkdictbi
/*
*
- * Copyright (C) 1996-2023, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#endif
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_BINARY */
-#endif
END_EXTERN_C
#include "dcmtk/ofstd/ofstd.h"
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
if (realLength > 0)
{
size_t i = OFstatic_cast(size_t, realLength);
- while ((i > 0) && (value[i - 1] == paddingChar))
+ while ((i > 0) && ((value[i - 1] == paddingChar) || (value[i - 1] == '\0')))
value[--i] = '\0';
realLength = OFstatic_cast(Uint32, i);
}
return NULL;
}
/* allocate space for extra padding character (required for the DICOM representation of the string) */
-#ifdef HAVE_STD__NOTHROW
+
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
value = new (std::nothrow) Uint8[lengthField + 2];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- value = new Uint8[lengthField + 2];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- value = NULL;
- }
-#endif
/* terminate string after real length */
if (value != NULL)
+ {
value[lengthField] = 0;
+ value[lengthField+1] = 0;
+ }
+
/* enforce old (pre DCMTK 3.5.2) behaviour? */
if (!dcmAcceptOddAttributeLength.get())
{
}
} else {
/* length is even, but we need an extra byte for the terminating 0 byte */
-#ifdef HAVE_STD__NOTHROW
+
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
value = new (std::nothrow) Uint8[lengthField + 1];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- value = new Uint8[lengthField + 1];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- value = NULL;
- }
-#endif
}
/* make sure that the string is properly terminated by a 0 byte */
if (value != NULL)
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcspchrs.h" /* for class DcmSpecificCharacterSet */
#include "dcmtk/dcmdata/dcitem.h" /* for class DcmItem */
#include "dcmtk/dcmdata/dcdeftag.h" /* for tag definitions */
-#include "dcmtk/dcmdata/dcjson.h" /* json helper classes */
+#include "dcmtk/dcmdata/dcjson.h" /* JSON helper classes */
#include "dcmtk/dcmdata/dcmatch.h"
//
OFCondition DcmCharString::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition result = EC_Normal;
+
/* always write JSON Opener */
DcmElement::writeJsonOpener(out, format);
+
/* write element value (if non-empty) */
if (!isEmpty())
{
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ result = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
+ OFString value;
OFCondition status = getOFString(value, 0L);
if (status.bad())
return status;
format.printValueSuffix(out);
}
}
+
/* write JSON Closer */
DcmElement::writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return result;
}
/*
*
- * Copyright (C) 1997-2023, OFFIS e.V.
+ * Copyright (C) 1997-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+Uint16 DcmCodecList::decodedBitsAllocated(
+ const DcmXfer & fromType,
+ Uint16 bitsAllocated,
+ Uint16 bitsStored)
+{
+#ifdef WITH_THREADS
+ if (! codecLock.initialized()) return 0; // should never happen
+#endif
+ Uint16 result = 0;
+
+ // acquire write lock on codec list. Will block if some write lock is currently active.
+#ifdef WITH_THREADS
+ OFReadWriteLocker locker(codecLock);
+ if (0 == locker.rdlock())
+ {
+#endif
+ E_TransferSyntax fromXfer = fromType.getXfer();
+ OFListIterator(DcmCodecList *) first = registeredCodecs.begin();
+ OFListIterator(DcmCodecList *) last = registeredCodecs.end();
+ while (first != last)
+ {
+ if ((*first)->codec->canChangeCoding(fromXfer, EXS_LittleEndianExplicit))
+ {
+ result = (*first)->codec->decodedBitsAllocated(bitsAllocated, bitsStored);
+ first = last;
+ } else ++first;
+ }
+#ifdef WITH_THREADS
+ } else result = 0;
+#endif
+ return result;
+}
+
+
OFCondition DcmCodecList::encode(
const E_TransferSyntax fromRepType,
const DcmRepresentationParameter * fromParam,
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// ********************************
-OFCondition DcmDataset::write(
- DcmOutputStream &outStream,
- const E_TransferSyntax oxfer,
- const E_EncodingType enctype /* = EET_UndefinedLength */,
- DcmWriteCache *wcache)
+OFCondition DcmDataset::write(DcmOutputStream &outStream,
+ const E_TransferSyntax oxfer,
+ const E_EncodingType enctype /* = EET_UndefinedLength */,
+ DcmWriteCache *wcache)
{
return write(outStream, oxfer, enctype, wcache, EGL_recalcGL);
}
return result;
}
+
+// ********************************
+
+void DcmDataset::initializeXfer(const E_TransferSyntax xfer)
+{
+ OriginalXfer = xfer;
+ CurrentXfer = xfer;
+}
/*
*
- * Copyright (C) 2002-2024, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
case ERT_Inventory:
recordName = "Inventory";
break;
+ case ERT_WfPresentation:
+ recordName = "WfPresentation";
+ break;
default:
recordName = "(unknown-directory-record-type)";
break;
result = ERT_Annotation;
else if (compare(sopClass, UID_InventoryStorage))
result = ERT_Inventory;
+ else if (compare(sopClass, UID_WaveformPresentationStateStorage) ||
+ compare(sopClass, UID_WaveformAcquisitionPresentationStateStorage))
+ {
+ result = ERT_WfPresentation;
+ }
return result;
}
case ERT_Assessment:
case ERT_Radiotherapy:
case ERT_Annotation:
+ case ERT_WfPresentation:
/* try to insert based on InstanceNumber */
result = insertWithISCriterion(parent, child, DCM_InstanceNumber);
break;
return compare(sopClassUID, UID_BreastProjectionXRayImageStorageForPresentation) ||
compare(sopClassUID, UID_BreastProjectionXRayImageStorageForProcessing) ||
compare(sopClassUID, UID_BreastTomosynthesisImageStorage) ||
+// in fact, the following IOD is a multi-frame image but the individual frames are rather "tiles"
+// compare(sopClassUID, UID_ConfocalMicroscopyTiledPyramidalImageStorage) ||
compare(sopClassUID, UID_EnhancedContinuousRTImageStorage) ||
compare(sopClassUID, UID_EnhancedCTImageStorage) ||
compare(sopClassUID, UID_EnhancedMRColorImageStorage) ||
compare(sopClassUID, UID_EnhancedUSVolumeStorage) ||
compare(sopClassUID, UID_EnhancedXAImageStorage) ||
compare(sopClassUID, UID_EnhancedXRFImageStorage) ||
+// compare(sopClassUID, UID_HeightMapSegmentationStorage) ||
compare(sopClassUID, UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation) ||
compare(sopClassUID, UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing) ||
+// compare(sopClassUID, UID_LabelMapSegmentationStorage) ||
compare(sopClassUID, UID_MultiframeGrayscaleByteSecondaryCaptureImageStorage) ||
compare(sopClassUID, UID_MultiframeGrayscaleWordSecondaryCaptureImageStorage) ||
compare(sopClassUID, UID_MultiframeSingleBitSecondaryCaptureImageStorage) ||
compare(sopClassUID, UID_OphthalmicPhotography16BitImageStorage) ||
compare(sopClassUID, UID_OphthalmicPhotography8BitImageStorage) ||
compare(sopClassUID, UID_OphthalmicTomographyImageStorage) ||
- compare(sopClassUID, UID_ParametricMapStorage) ||
- compare(sopClassUID, UID_RTDoseStorage) ||
+// compare(sopClassUID, UID_ParametricMapStorage) ||
+ compare(sopClassUID, UID_PhotoacousticImageStorage) ||
+// compare(sopClassUID, UID_RTDoseStorage) ||
compare(sopClassUID, UID_RTImageStorage) ||
compare(sopClassUID, UID_UltrasoundMultiframeImageStorage) ||
compare(sopClassUID, UID_VideoEndoscopicImageStorage) ||
metainfo->findAndGetOFStringArray(DCM_TransferSyntaxUID, transferSyntax);
metainfo->findAndGetOFStringArray(DCM_MediaStorageSOPClassUID, mediaSOPClassUID);
E_DirRecType recordType = sopClassToRecordType(mediaSOPClassUID);
- /* hanging protocol, palette and implant files are handled separately */
+ /* some directory record types are handled separately */
if (recordType == ERT_HangingProtocol)
{
/* check whether all type 1 elements are really present */
}
break;
case ERT_Presentation:
+ case ERT_WfPresentation:
if (!checkExistsWithValue(dataset, DCM_InstanceNumber, filename))
result = EC_MissingAttribute;
if (!checkExistsWithValue(dataset, DCM_ContentLabel, filename))
case ERT_Radiotherapy:
case ERT_Annotation:
case ERT_Inventory:
+ case ERT_WfPresentation:
/* The attribute ReferencedSOPInstanceUID is automatically
* put into a Directory Record when a filename is present.
*/
}
+// create or update waveform presentation state record and copy required values from dataset
+DcmDirectoryRecord *DicomDirInterface::buildWfPresentationRecord(DcmDirectoryRecord *record,
+ DcmFileFormat *fileformat,
+ const OFString &referencedFileID,
+ const OFFilename &sourceFilename)
+{
+ /* create new waveform presentation record */
+ if (record == NULL)
+ record = new DcmDirectoryRecord(ERT_WfPresentation, referencedFileID.c_str(), sourceFilename, fileformat);
+ if (record != NULL)
+ {
+ /* check whether new record is ok */
+ if (record->error().good())
+ {
+ DcmDataset *dataset = fileformat->getDataset();
+ /* copy attribute values from dataset to waveform presentation record */
+ copyElementType1(dataset, DCM_InstanceNumber, record, sourceFilename);
+ copyElementType1(dataset, DCM_ContentLabel, record, sourceFilename);
+ copyElementType2(dataset, DCM_ContentDescription, record, sourceFilename);
+ copyElementType1(dataset, DCM_PresentationCreationDate, record, sourceFilename);
+ copyElementType1(dataset, DCM_PresentationCreationTime, record, sourceFilename);
+ copyElementType3(dataset, DCM_ContentCreatorName, record, sourceFilename);
+ copyElementType1C(dataset, DCM_ReferencedSeriesSequence, record, sourceFilename);
+ // tbd: need to check content of the referenced series sequence
+ } else {
+ printRecordErrorMessage(record->error(), ERT_WfPresentation, "create");
+ /* free memory */
+ delete record;
+ record = NULL;
+ }
+ } else
+ printRecordErrorMessage(EC_MemoryExhausted, ERT_WfPresentation, "create");
+ return record;
+}
+
+
// create or update waveform record and copy required values from dataset
DcmDirectoryRecord *DicomDirInterface::buildWaveformRecord(DcmDirectoryRecord *record,
DcmFileFormat *fileformat,
case ERT_Inventory:
record = buildInventoryRecord(record, fileformat, referencedFileID, sourceFilename);
break;
+ case ERT_WfPresentation:
+ record = buildWfPresentationRecord(record, fileformat, referencedFileID, sourceFilename);
+ break;
default:
/* it can only be an image */
record = buildImageRecord(record, fileformat, referencedFileID, sourceFilename);
case ERT_Assessment:
case ERT_Radiotherapy:
case ERT_Annotation:
+ case ERT_WfPresentation:
if (!record->tagExistsWithValue(DCM_InstanceNumber))
setDefaultValue(record, DCM_InstanceNumber, AutoInstanceNumber++);
break;
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
size_t len;
do {
-#ifdef __BORLANDC__
+#ifdef HAVE_CLASSIC_BORLAND_COMPILER
// Borland Builder expects a non-const argument
p = strchr(OFconst_cast(char *, line), splitChar);
#else
**
** User: joergr
** Host: thinkpad2
-** Date: 2024-11-16 10:42:05
+** Date: 2025-11-21 11:54:35
** Prog: /home/joergr/Source/dcmtk-full/public/dcmdata/libsrc/mkdictbi
**
** From: ../data/dicom.dic
EVR_SQ, "RelatedSeriesSequence", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0008, 0x1301, 0x0008, 0x1301,
+ EVR_SQ, "PrincipalDiagnosisCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0008, 0x1302, 0x0008, 0x1302,
+ EVR_SQ, "PrimaryDiagnosisCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0008, 0x1303, 0x0008, 0x1303,
+ EVR_SQ, "SecondaryDiagnosesCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0008, 0x1304, 0x0008, 0x1304,
+ EVR_SQ, "HistologicalDiagnosesCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0008, 0x2110, 0x0008, 0x2110,
EVR_CS, "RETIRED_LossyImageCompressionRetired", 1, 1, "DICOM/retired",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_PN, "PatientName", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0010, 0x0011, 0x0010, 0x0011,
+ EVR_SQ, "PersonNamesToUseSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0012, 0x0010, 0x0012,
+ EVR_LT, "NameToUse", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0013, 0x0010, 0x0013,
+ EVR_UT, "NameToUseComment", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0014, 0x0010, 0x0014,
+ EVR_SQ, "ThirdPersonPronounsSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0015, 0x0010, 0x0015,
+ EVR_SQ, "PronounCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0016, 0x0010, 0x0016,
+ EVR_UT, "PronounComment", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0010, 0x0020, 0x0010, 0x0020,
EVR_LO, "PatientID", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_CS, "PatientSex", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0010, 0x0041, 0x0010, 0x0041,
+ EVR_SQ, "GenderIdentitySequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0042, 0x0010, 0x0042,
+ EVR_UT, "SexParametersForClinicalUseCategoryComment", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0043, 0x0010, 0x0043,
+ EVR_SQ, "SexParametersForClinicalUseCategorySequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0044, 0x0010, 0x0044,
+ EVR_SQ, "GenderIdentityCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0045, 0x0010, 0x0045,
+ EVR_UT, "GenderIdentityComment", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0046, 0x0010, 0x0046,
+ EVR_SQ, "SexParametersForClinicalUseCategoryCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0010, 0x0047, 0x0010, 0x0047,
+ EVR_UR, "SexParametersForClinicalUseCategoryReference", 1, -1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0010, 0x0050, 0x0010, 0x0050,
EVR_SQ, "PatientInsurancePlanCodeSequence", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
, { 0x0010, 0x2160, 0x0010, 0x2160,
- EVR_SH, "EthnicGroup", 1, 1, "DICOM",
+ EVR_SH, "RETIRED_EthnicGroup", 1, 1, "DICOM/retired",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
, { 0x0010, 0x2161, 0x0010, 0x2161,
EVR_SQ, "EthnicGroupCodeSequence", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0010, 0x2162, 0x0010, 0x2162,
+ EVR_UC, "EthnicGroups", 1, -1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0010, 0x2180, 0x0010, 0x2180,
EVR_SH, "Occupation", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_LO, "ImageQualityIndicatorSize", 1, -1, "DICOM/DICONDE",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0014, 0x4101, 0x0014, 0x4101,
+ EVR_SQ, "WaveDimensionsDefinitionSequence", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4102, 0x0014, 0x4102,
+ EVR_US, "WaveDimensionNumber", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4103, 0x0014, 0x4103,
+ EVR_LO, "WaveDimensionDescription", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4104, 0x0014, 0x4104,
+ EVR_US, "WaveDimensionUnit", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4105, 0x0014, 0x4105,
+ EVR_CS, "WaveDimensionValueType", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4106, 0x0014, 0x4106,
+ EVR_SQ, "WaveDimensionValuesSequence", 1, -1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4107, 0x0014, 0x4107,
+ EVR_US, "ReferencedWaveDimension", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4108, 0x0014, 0x4108,
+ EVR_SL, "IntegerNumericValue", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x4109, 0x0014, 0x4109,
+ EVR_OB, "ByteNumericValue", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x410a, 0x0014, 0x410a,
+ EVR_OW, "ShortNumericValue", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x410b, 0x0014, 0x410b,
+ EVR_OF, "SinglePrecisionFloatingPointNumericValue", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0014, 0x410c, 0x0014, 0x410c,
+ EVR_OD, "DoublePrecisionFloatingPointNumericValue", 1, 1, "DICOM/DICONDE",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0014, 0x5002, 0x0014, 0x5002,
EVR_IS, "LINACEnergy", 1, 1, "DICOM/DICONDE",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_DT, "ObservationStartDateTime", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0040, 0xa034, 0x0040, 0xa034,
+ EVR_DT, "EffectiveStartDateTime", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xa035, 0x0040, 0xa035,
+ EVR_DT, "EffectiveStopDateTime", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0040, 0xa040, 0x0040, 0xa040,
EVR_CS, "ValueType", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_SQ, "WaveformAnnotationSequence", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0040, 0xb030, 0x0040, 0xb030,
+ EVR_SQ, "StructuredWaveformAnnotationSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb031, 0x0040, 0xb031,
+ EVR_SQ, "WaveformAnnotationDisplaySelectionSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb032, 0x0040, 0xb032,
+ EVR_US, "ReferencedMontageIndex", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb033, 0x0040, 0xb033,
+ EVR_SQ, "WaveformTextualAnnotationSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb034, 0x0040, 0xb034,
+ EVR_DT, "AnnotationDateTime", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb035, 0x0040, 0xb035,
+ EVR_SQ, "DisplayedWaveformSegmentSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb036, 0x0040, 0xb036,
+ EVR_DT, "SegmentDefinitionDateTime", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb037, 0x0040, 0xb037,
+ EVR_SQ, "MontageActivationSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb038, 0x0040, 0xb038,
+ EVR_DS, "MontageActivationTimeOffset", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb039, 0x0040, 0xb039,
+ EVR_SQ, "WaveformMontageSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb03a, 0x0040, 0xb03a,
+ EVR_IS, "ReferencedMontageChannelNumber", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb03b, 0x0040, 0xb03b,
+ EVR_LT, "MontageName", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb03c, 0x0040, 0xb03c,
+ EVR_SQ, "MontageChannelSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb03d, 0x0040, 0xb03d,
+ EVR_US, "MontageIndex", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb03e, 0x0040, 0xb03e,
+ EVR_IS, "MontageChannelNumber", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb03f, 0x0040, 0xb03f,
+ EVR_LO, "MontageChannelLabel", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb040, 0x0040, 0xb040,
+ EVR_SQ, "MontageChannelSourceCodeSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb041, 0x0040, 0xb041,
+ EVR_SQ, "ContributingChannelSourcesSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x0040, 0xb042, 0x0040, 0xb042,
+ EVR_FL, "ChannelWeight", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0040, 0xdb00, 0x0040, 0xdb00,
EVR_CS, "TemplateIdentifier", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_SQ, "OrganizationalRoleCodeSequence", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0044, 0x0110, 0x0044, 0x0110,
+ EVR_SQ, "RTAssertionsSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
#ifdef ENABLE_PRIVATE_TAGS
, { 0x0045, 0x0004, 0x0045, 0x0004,
EVR_CS, "AES", 1, 1, "PrivateTag",
EVR_UL, "TotalPixelMatrixFocalPlanes", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x0048, 0x0304, 0x0048, 0x0304,
+ EVR_CS, "TilesOverlap", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x0050, 0x0004, 0x0050, 0x0004,
EVR_CS, "CalibrationImage", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_DS, "DVHMeanDose", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x3004, 0x0080, 0x3004, 0x0080,
+ EVR_SQ, "DoseCalculationModelSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x3004, 0x0081, 0x3004, 0x0081,
+ EVR_SQ, "DoseCalculationAlgorithmSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x3004, 0x0082, 0x3004, 0x0082,
+ EVR_CS, "CommissioningStatus", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x3004, 0x0083, 0x3004, 0x0083,
+ EVR_SQ, "DoseCalculationModelParameterSequence", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x3004, 0x0084, 0x3004, 0x0084,
+ EVR_CS, "DoseDepositionCalculationMedium", 1, 1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x3006, 0x0002, 0x3006, 0x0002,
EVR_SH, "StructureSetLabel", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
EVR_IS, "NumberOfPaintings", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
NULL }
+ , { 0x300a, 0x039b, 0x300a, 0x039b,
+ EVR_FL, "ScanSpotGantryAngles", 1, -1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
+ , { 0x300a, 0x039c, 0x300a, 0x039c,
+ EVR_FL, "ScanSpotPatientSupportAngles", 1, -1, "DICOM",
+ DcmDictRange_Unspecified, DcmDictRange_Unspecified,
+ NULL }
, { 0x300a, 0x03a0, 0x300a, 0x03a0,
EVR_SQ, "IonToleranceTableSequence", 1, 1, "DICOM",
DcmDictRange_Unspecified, DcmDictRange_Unspecified,
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
"ASSESSMENT",
"RADIOTHERAPY",
"ANNOTATION",
- "INVENTORY"
+ "INVENTORY",
+ "WF PRESENTATION"
};
static const short DIM_OF_DRTypeNames = OFstatic_cast(short, (sizeof(DRTypeNames) / sizeof(DRTypeNames[0])));
case ERT_Assessment:
case ERT_Radiotherapy:
case ERT_Annotation:
+ case ERT_WfPresentation:
case ERT_Private:
l_error = EC_Normal;
break;
case ERT_Radiotherapy:
case ERT_Annotation:
case ERT_Inventory:
+ case ERT_WfPresentation:
case ERT_Private:
switch (lowerRecord)
{
--- /dev/null
+/*
+ *
+ * Copyright (C) 2007-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Marco Eichelberg, Tingyan Xu
+ *
+ * Purpose: Helper class for extracting encapsulated file from a DICOM encapsulated storage object
+ *
+ */
+
+//make sure OS specific configuration is included first
+#include "dcmtk/config/osconfig.h"
+#include "dcmtk/dcmdata/dcdocdec.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/dcmdata/dcuid.h"
+
+BEGIN_EXTERN_C
+#include <fcntl.h> /* for O_BINARY */
+#ifdef HAVE_IO_H
+#include <io.h> /* for setmode() on Windows */
+#endif
+END_EXTERN_C
+
+
+DcmDocumentDecapsulator::DcmDocumentDecapsulator()
+: readMode_(ERM_autoDetect)
+, inputXfer_(EXS_Unknown)
+, execString_(NULL)
+, inputFname_(NULL)
+, outputFname_(NULL)
+, dicomFile_()
+{
+}
+
+
+DcmDocumentDecapsulator::~DcmDocumentDecapsulator()
+{
+}
+
+
+OFCondition DcmDocumentDecapsulator::loadDICOMFile()
+{
+ // check filename
+ if ((inputFname_ == NULL) || (strlen(inputFname_) == 0))
+ {
+ DCMDATA_ERROR("invalid input filename: <empty string>");
+ return EC_InvalidFilename;
+ }
+
+ // read DICOM file
+ DCMDATA_INFO("open input file " << inputFname_);
+ OFCondition cond = dicomFile_.loadFile(inputFname_, inputXfer_, EGL_noChange, DCM_MaxReadLength, readMode_);
+ if (cond.bad())
+ {
+ DCMDATA_ERROR(cond.text() << ": reading file: " << inputFname_);
+ return cond;
+ }
+
+ return EC_Normal;
+}
+
+
+OFCondition DcmDocumentDecapsulator::writeEncapsulatedContentToFile()
+{
+ // check filename
+ if ((outputFname_ == NULL) || (strlen(outputFname_) == 0))
+ {
+ DCMDATA_ERROR("invalid output filename: <empty string>");
+ return EC_InvalidFilename;
+ }
+
+ // get encapsulated document
+ DcmDataset* dataset = dicomFile_.getDataset();
+ DcmElement *delem = NULL;
+ OFCondition cond = dataset->findAndGetElement(DCM_EncapsulatedDocument, delem);
+ if (cond.bad() || delem == NULL)
+ {
+ DCMDATA_ERROR("encapsulated document missing");
+ return EC_MissingAttribute;
+ }
+
+ Uint32 len = delem->getLength();
+ Uint8 *encapDocment = NULL;
+ cond = delem->getUint8Array(encapDocment);
+ if (cond.bad() || encapDocment == NULL || len == 0)
+ {
+ DCMDATA_ERROR("encapsulated Document empty or wrong VR");
+ return EC_MissingAttribute;
+ }
+
+ // get and check element encapsulated document length
+ Uint32 lenElem;
+ cond = dataset->findAndGetUint32(DCM_EncapsulatedDocumentLength, lenElem);
+
+ // EncapsulatedDocumentLength Element is invalid or
+ // it does not fit the length of the encapsulated document
+ // (it has to be equal or equal to EncapsulatedDocumentLength -1)
+ if (cond.bad() || (lenElem != len && lenElem != len - 1))
+ {
+ DCMDATA_DEBUG("EncapsulatedDocumentLength missing or invalid, using length of EncapsulatedDocument");
+ lenElem = len;
+
+ // try to retrieve the SOP Class UID, ignore errors
+ OFString sopClass;
+ (void) dataset->findAndGetOFString(DCM_SOPClassUID, sopClass);
+
+ // try to determine if we need to strip a pad byte at the end of the element
+ if (sopClass == UID_EncapsulatedPDFStorage)
+ {
+ // The PDF format expects files to end with %%EOF followed by CR/LF
+ // (although in some cases the CR/LF may be missing or you might only find CR or LF).
+ // If the last character of the file is not a CR or LF, and not the
+ // letter 'F', we assume it is either trailing garbage or a pad byte, and remove it.
+ if (encapDocment[lenElem-1] != 10 && encapDocment[lenElem-1] != 13 && encapDocment[lenElem-1] != 'F')
+ {
+ DCMDATA_DEBUG("removing pad byte at end of encapsulated document");
+ --lenElem;
+ }
+ }
+ else if (sopClass == UID_EncapsulatedCDAStorage)
+ {
+ // CDA documents end with a closing XML tag, optionally followed by whitespace.
+ // If the last character of the file is not a CR ('\r', 13) or LF ('\n', 10), and not the
+ // letter '>', we assume it is either trailing garbage or a pad byte, and remove it.
+ if (encapDocment[lenElem - 1] != '\n' && encapDocment[lenElem - 1] != '\r' && encapDocment[lenElem - 1] != '>')
+ {
+ DCMDATA_DEBUG("removing pad byte at end of encapsulated document");
+ --lenElem;
+ }
+ }
+ else if (sopClass == UID_EncapsulatedSTLStorage || sopClass == UID_EncapsulatedOBJStorage || sopClass == UID_EncapsulatedMTLStorage)
+ {
+ // STL, OBJ and MTL are text formats. We remove a trailing null byte, but nothing else.
+ if (encapDocment[lenElem - 1] == '\0')
+ {
+ DCMDATA_DEBUG("removing pad byte at end of encapsulated document");
+ --lenElem;
+ }
+ }
+ else
+ {
+ DCMDATA_DEBUG("Unknown encapsulated document SOP class, not removing any pad byte");
+ }
+ }
+
+ DCMDATA_INFO( "writing encapsulated document to " << outputFname_);
+
+ if (strcmp(outputFname_, "-") == 0)
+ {
+#ifdef _WIN32
+ // Set "stdout" to binary mode
+ if (setmode(fileno(stdout), O_BINARY) == -1)
+ {
+ DCMDATA_ERROR("Failed to switch stdout to binary mode");
+ return makeOFCondition(OFM_dcmdata, 19, OF_error, "file write error");
+ }
+#endif
+
+ // write encapsulated document to stdout
+ if (lenElem != fwrite(encapDocment, 1, lenElem, stdout))
+ {
+ DCMDATA_ERROR("write error to stdout");
+ return makeOFCondition(OFM_dcmdata, 19, OF_error, "file write error");
+ }
+ }
+ else
+ {
+ // write encapsulated document to file
+ OFFile encapfile;
+ if (!encapfile.fopen(outputFname_, "wb"))
+ {
+ DCMDATA_ERROR("unable to create file " << outputFname_);
+ return makeOFCondition(OFM_dcmdata, 19, OF_error, "file open error");
+ }
+
+ if (lenElem != encapfile.fwrite(encapDocment, 1, lenElem))
+ {
+ DCMDATA_ERROR("write error in file " << outputFname_);
+ (void) encapfile.fclose();
+ return makeOFCondition(OFM_dcmdata, 19, OF_error, "file write error");
+ }
+
+ if (encapfile.fclose())
+ {
+ DCMDATA_ERROR("write error in file " << outputFname_);
+ return makeOFCondition(OFM_dcmdata, 19, OF_error, "file close error");
+ }
+ }
+
+ DCMDATA_INFO( "conversion successful");
+ return EC_Normal;
+}
+
+
+/** Replace all occurrences of pattern in srcstr with substitute and return
+ * the result as a new OFString variable.
+ * @param srcstr source string
+ * @param pattern pattern string to be substituted.
+ * @param substitute substitute for occurences of pattern in srcstr
+ * @return string with patterns replaced
+ */
+static OFString replaceChars(const OFString &srcstr, const OFString &pattern, const OFString &substitute)
+{
+ OFString result = srcstr;
+ size_t pos = 0;
+
+ while (pos != OFString_npos)
+ {
+ pos = result.find(pattern, pos);
+
+ if (pos != OFString_npos)
+ {
+ result.replace(pos, pattern.size(), substitute);
+ pos += substitute.size();
+ }
+ }
+
+ return result;
+}
+
+
+#define FILENAME_PLACEHOLDER "#f"
+
+OFCondition DcmDocumentDecapsulator::executeCommand()
+{
+ if (execString_)
+ {
+ OFString cmdStr = replaceChars(execString_, OFString(FILENAME_PLACEHOLDER), outputFname_);
+
+ // Execute command and return result
+ if (system(cmdStr.c_str()) != 0) return EC_CommandLineFailed;
+ }
+ return EC_Normal;
+}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// is added to the Length for this purpose.
if (getLengthField() & 1)
{
-#ifdef HAVE_STD__NOTHROW
// we want to use a non-throwing new here if available
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
fValue = new (std::nothrow) Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- fValue = new Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- fValue = NULL;
- }
-#endif
+
if (fValue)
fValue[getLengthField()] = 0;
setLengthField(getLengthField() + 1); // make Length even
}
else
{
-#ifdef HAVE_STD__NOTHROW
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
fValue = new (std::nothrow) Uint8[getLengthField() + pad];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- fValue = new Uint8[getLengthField() + pad];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- fValue = NULL;
- }
-#endif
}
if (!fValue)
{
if (this != &obj)
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
delete fLoadValue;
fLoadValue = NULL;
fValue = NULL;
if (getLengthField() & 1)
{
-#ifdef HAVE_STD__NOTHROW
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
fValue = new (std::nothrow) Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- fValue = new Uint8[getLengthField() + 1 + pad]; // protocol error: odd value length
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- fValue = NULL;
- }
-#endif
if (fValue)
fValue[getLengthField()] = 0;
setLengthField(getLengthField() + 1); // make Length even
}
else
{
-#ifdef HAVE_STD__NOTHROW
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
fValue = new (std::nothrow) Uint8[getLengthField() + pad];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- fValue = new Uint8[getLengthField() + pad];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- fValue = NULL;
- }
-#endif
}
if (!fValue)
DcmElement::~DcmElement()
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
delete fLoadValue;
}
OFCondition DcmElement::clear()
{
errorFlag = EC_Normal;
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
fValue = NULL;
delete fLoadValue;
fLoadValue = NULL;
if (l_error.good())
{
Uint8 * newValue;
-#ifdef HAVE_STD__NOTHROW
// we want to use a non-throwing new here if available
newValue = new (std::nothrow) Uint8[getLengthField()];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- newValue = new Uint8[getLengthField()];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- newValue = NULL;
- }
-#endif
+
if (newValue)
{
memcpy(newValue, fValue, size_t(getLengthField()));
return NULL;
}
/* create an array of Length+1 bytes */
-#ifdef HAVE_STD__NOTHROW
+
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
value = new (std::nothrow) Uint8[lengthField + 1]; // protocol error: odd value length
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- value = new Uint8[lengthField + 1]; // protocol error: odd value length
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- value = NULL;
- }
-#endif
+
/* if creation was successful, set last byte to 0 (in order to initialize this byte) */
/* (no value will be assigned to this byte later, since Length was odd) */
if (value)
}
/* if this element's length is even, create a corresponding array of Length bytes */
else
-#ifdef HAVE_STD__NOTHROW
+ {
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
value = new (std::nothrow) Uint8[lengthField];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- value = new Uint8[lengthField];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- value = NULL;
- }
-#endif
+ }
+
/* if creation was not successful set member error flag correspondingly */
if (!value)
errorFlag = EC_MemoryExhausted;
{
Uint8 * newValue;
// allocate new memory for value
-#ifdef HAVE_STD__NOTHROW
+
// we want to use a non-throwing new here if available.
// If the allocation fails, we report an EC_MemoryExhausted error
// back to the caller.
newValue = new (std::nothrow) Uint8[getLengthField() + num];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- newValue = new Uint8[getLengthField() + num];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- newValue = NULL;
- }
-#endif
+
if (!newValue)
errorFlag = EC_MemoryExhausted;
if (errorFlag.good())
memcpy(newValue, fValue, size_t(getLengthField()));
// copy value passed as a parameter to the end
memcpy(&newValue[getLengthField()], OFstatic_cast(const Uint8 *, value), size_t(num));
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
fValue = newValue;
setLengthField(getLengthField() + num);
} else
}
+OFCondition DcmElement::putSint64(const Sint64 /*val*/,
+ const unsigned long /*pos*/)
+{
+ errorFlag = EC_IllegalCall;
+ return errorFlag;
+}
+
+
+OFCondition DcmElement::putUint64(const Uint64 /*val*/,
+ const unsigned long /*pos*/)
+{
+ errorFlag = EC_IllegalCall;
+ return errorFlag;
+}
+
OFCondition DcmElement::putFloat64(const Float64 /*val*/,
const unsigned long /*pos*/)
{
}
+OFCondition DcmElement::putSint64Array(const Sint64 * /*val*/,
+ const unsigned long /*num*/)
+{
+ errorFlag = EC_IllegalCall;
+ return errorFlag;
+}
+
+
+OFCondition DcmElement::putUint64Array(const Uint64 * /*val*/,
+ const unsigned long /*num*/)
+{
+ errorFlag = EC_IllegalCall;
+ return errorFlag;
+}
+
OFCondition DcmElement::putFloat64Array(const Float64 * /*val*/,
const unsigned long /*num*/)
{
if (fValue)
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
}
fValue = NULL;
errorFlag = EC_Normal;
if (fValue)
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
}
fValue = NULL;
if (fLoadValue)
if (fLoadValue)
{
- offile_off_t skipped = inStream.skip(getLengthField());
- if (skipped < OFstatic_cast(offile_off_t, getLengthField()))
+ /* enforce old (pre DCMTK 3.5.2) behaviour ? */
+ Uint32 lengthField = getLengthField();
+ if ((lengthField & 1) && !dcmAcceptOddAttributeLength.get())
+ {
+ lengthField++;
+ setLengthField(lengthField); // make Length even
+ }
+
+ offile_off_t skipped = inStream.skip(lengthField);
+ if (skipped < OFstatic_cast(offile_off_t, lengthField))
{
/* If desired, specific parser errors will be ignored */
if (dcmIgnoreParsingErrors.get())
}
}
/* if there is already a value for this element, delete this value */
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
/* set the transfer state to ERW_inWork */
setTransferState(ERW_inWork);
}
OFCondition DcmElement::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition result = EC_Normal;
+
/* always write JSON Opener */
writeJsonOpener(out, format);
+
/* write element value (if non-empty) */
if (!isEmpty())
{
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ result = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
+ OFString value;
OFCondition status = getOFString(value, 0L);
if (status.bad())
return status;
format.printValueSuffix(out);
}
}
+
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return result;
}
{
if (factory && !(length & 1))
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
// if created with the nothrow version it must also be deleted with
// the nothrow version else memory error.
operator delete[] (fValue, std::nothrow);
-#else
- delete[] fValue;
-#endif
fValue = 0;
delete fLoadValue;
fLoadValue = factory;
}
+Uint16 DcmElement::decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const
+{
+ // Note: This method only handles the uncompressed case.
+ // A different implementation is provided in class DcmPixelData.
+ if (bitsStored > bitsAllocated) return 0;
+ return bitsAllocated;
+}
+
+
// the following macro makes the source code more readable and easier to maintain
#define GET_AND_CHECK_UINT16_VALUE(tag, variable) \
Uint16 cols = 0;
Uint16 samplesPerPixel = 0;
Uint16 bitsAllocated = 0;
+ Uint16 bitsStored = 0;
Sint32 numberOfFrames = 1;
OFString photometricInterpretation;
/* see PS3.3 Table C.7-11c: "Bits Allocated (0028,0100) shall be either 1, or a multiple of 8." */
else if ((bitsAllocated == 0) || ((bitsAllocated > 1) && (bitsAllocated % 8 != 0)))
DCMDATA_WARN("DcmElement: Dubious value (" << bitsAllocated << ") for element BitsAllocated " << DCM_BitsAllocated);
+
+ GET_AND_CHECK_UINT16_VALUE(DCM_BitsStored, bitsStored)
+ else if (bitsStored > bitsAllocated)
+ {
+ DCMDATA_WARN("DcmElement: Dubious value (" << bitsStored << ") for element BitsStored " << DCM_BitsAllocated << " larger than value of BitsAllocated " << DCM_BitsAllocated);
+ result = EC_InvalidValue;
+ }
}
+
/* if all checks were passed... */
if (result.good())
{
DCMDATA_WARN("DcmElement: failed to compute size of PixelData element");
}
- /* compute frame size (TODO: check for 32-bit integer overflow?) */
- if ((bitsAllocated % 8) == 0)
+ // Determine the effective value for Bits Allocated, taking into account compression
+ Uint16 effectiveBitsAllocated = decodedBitsAllocated(bitsAllocated, bitsStored);
+ if (effectiveBitsAllocated == 0)
{
- const Uint16 bytesAllocated = bitsAllocated / 8;
- frameSize = bytesAllocated * rows * cols * samplesPerPixel;
+ DCMDATA_WARN("DcmElement: Encapsulated image with BitsAllocated=" << bitsAllocated << " and BitsStored=" << bitsStored << " cannot be decoded");
+ result = EC_InvalidValue;
}
else
{
- /* need to split calculation in order to avoid integer overflow for large pixel data */
- const Uint32 v1 = rows * cols * samplesPerPixel;
- const Uint32 v2 = (bitsAllocated / 8) * v1;
- const Uint32 v3 = ((bitsAllocated % 8) * v1 + 7) / 8;
- // # old code: frameSize = (bitsAllocated * rows * cols * samplesPerPixel + 7) / 8;
- frameSize = v2 + v3;
+ /* compute frame size */
+ if ((effectiveBitsAllocated % 8) == 0)
+ {
+ const Uint16 bytesAllocated = effectiveBitsAllocated / 8;
+ const Uint32 v1 = rows * cols * samplesPerPixel;
+ frameSize = bytesAllocated * v1;
+ if (frameSize / bytesAllocated != v1)
+ {
+ DCMDATA_WARN("DcmElement: frame size too large, 32-bit integer overflow");
+ result = EC_InvalidValue;
+ }
+ }
+ else
+ {
+ // Split the calculation in order to avoid integer overflow for large pixel data.
+ // # old code: frameSize = (effectiveBitsAllocated * rows * cols * samplesPerPixel + 7) / 8;
+ const Uint32 v1 = rows * cols * samplesPerPixel;
+ const Uint32 v2 = (effectiveBitsAllocated / 8) * v1;
+ const Uint32 v3 = ((effectiveBitsAllocated % 8) * v1 + 7) / 8;
+ frameSize = v2 + v3;
+ }
}
- } else {
- /* in case of error, return a frame size of 0 */
- frameSize = 0;
}
}
+
+ /* in case of error, return a frame size of 0 */
+ if (result.bad()) frameSize = 0;
return result;
}
/*
*
- * Copyright (C) 2018-2024, OFFIS e.V.
+ * Copyright (C) 2018-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*
* Module: dcmdata
*
- * Author: Pedro ArizpeGomez
+ * Author: Pedro ArizpeGomez, Marco Eichelberg
*
* Purpose: Implementation of Document encapsulation
*
#define SHORTCOL 3
#define LONGCOL 21
-// exit codes for this command line tool
-// (common codes are defined in "ofexit.h" included from "ofconapp.h")
-
-// general errors
-#define EXITCODE_MEMORY_EXHAUSTED 4
-
-DcmEncapsulatedDocument::DcmEncapsulatedDocument() :
- opt_patientBirthdate(),
- opt_patientID(),
- opt_patientName(),
- opt_patientSex(),
-
- opt_conceptCM(),
- opt_conceptCSD(),
- opt_conceptCV(),
-
- opt_documentTitle(),
- opt_seriesFile(),
- opt_seriesUID(),
- opt_studyUID(),
-
- opt_oenctype(EET_ExplicitLength),
- opt_writeMode(EWM_fileformat),
- opt_oglenc(EGL_withoutGL),
- opt_opadenc(EPD_withoutPadding),
- opt_oxfer(EXS_LittleEndianExplicit),
- opt_filepad(0),
- opt_itempad(0),
-
- opt_readSeriesInfo(OFFalse),
- opt_annotation(OFTrue),
- opt_increment(OFFalse),
-
- opt_instance(1),
- opt_overrideKeys(),
-
- cda_mediaTypes(),
- hl7_InstanceIdentifier(),
- opt_override(OFFalse),
- // Frame of Reference Module (STL)
- opt_frameOfReferenceUID(),
- opt_positionReferenceIndicator(),
- // Frame of Reference Module (STL)
- opt_manufacturer(),
- opt_manufacturerModelName(),
- opt_deviceSerialNumber(),
- opt_softwareVersions(),
- // Enhanced General Equipment Module (STL)
- opt_measurementUnitsCM(),
- opt_measurementUnitsCSD(),
- opt_measurementUnitsCV(),
- //encapsulation file type
- ftype()
+DcmEncapsulatedDocument::DcmEncapsulatedDocument()
+: patientBirthdate_()
+, patientID_()
+, patientName_()
+, patientSex_()
+, conceptCM_()
+, conceptCSD_()
+, conceptCV_()
+, documentTitle_()
+, seriesFile_()
+, seriesUID_()
+, studyUID_()
+, specificCharSet_()
+, modality_()
+, oenctype_(EET_ExplicitLength)
+, writeMode_(EWM_fileformat)
+, oglenc_(EGL_withoutGL)
+, opadenc_(EPD_withoutPadding)
+, oxfer_(EXS_LittleEndianExplicit)
+, filepad_(0)
+, itempad_(0)
+, readSeriesInfo_(OFFalse)
+, annotation_(OFTrue)
+, increment_(OFFalse)
+, instance_(1)
+, overrideKeys_()
+, cda_mediaTypes()
+, hl7_InstanceIdentifier()
+, override_(OFFalse)
+, frameOfReferenceUID_()
+, positionReferenceIndicator_()
+, manufacturer_()
+, manufacturerModelName_()
+, deviceSerialNumber_()
+, softwareVersions_()
+, measurementUnitsCM_()
+, measurementUnitsCSD_()
+, measurementUnitsCV_()
+, ftype_(DT_unknownDocument)
+, dfile_()
{
}
-OFBool DcmEncapsulatedDocument::XMLsearchAttribute(
+
+DcmEncapsulatedDocument::~DcmEncapsulatedDocument()
+{
+}
+
+// ========== static helper functions for processing CDA documents ==========
+
+/** Recursive function used by getAttributeValues to get all occurrences of an attribute as a list.
+ * @param currnode the current XML node to be processed.
+ * @param list of strings to which the results are added.
+ * @param attr the attribute to search for.
+ * @return OFTrue if the attribute value was found, OFFalse otherwise.
+ */
+static OFBool XMLsearchAttribute(
XMLNode currnode,
- OFList<OFString> *results,
- OFString attr)
+ OFList<OFString> &results,
+ const OFString& attr)
{
OFBool found = OFFalse;
#ifndef _XMLWIDECHAR
if (currnode.nChildNode() == 0)
{
- //"currnode has no children (leaf)";
+ // currnode has no children (leaf)
if (currnode.isAttributeSet(attr.c_str()))
{
//attribute found on leaf
- results->push_back(OFSTRING_GUARD(currnode.getAttribute(attr.c_str())));
+ results.push_back(OFSTRING_GUARD(currnode.getAttribute(attr.c_str())));
found = OFTrue;
}
}
else
{
- //"currnode has children (branch)";
+ // currnode has children (branch)
if (currnode.isAttributeSet(attr.c_str()))
{
//attribute found on branch
- results->push_back(OFSTRING_GUARD(currnode.getAttribute(attr.c_str())));
+ results.push_back(OFSTRING_GUARD(currnode.getAttribute(attr.c_str())));
found = OFTrue;
}
for (int i = 0; i < currnode.nChildNode(); i++)
{
//search all children recursively
- OFBool childfound = XMLsearchAttribute(currnode.getChildNode(i), results, attr);
- found |= childfound;
+ found |= XMLsearchAttribute(currnode.getChildNode(i), results, attr);
}
}
#endif
return found;
}
-OFString DcmEncapsulatedDocument::XMLgetAllAttributeValues(
- XMLNode fileNode,
- OFString attr)
+
+/** Retrieve all entries of an attribute and returns them as a string, separated by backslashes.
+ * @param fileNode the root XML node.
+ * @param attr the attribute to search for.
+ * @return OFstring containing all entries found, separated by backslashes
+ */
+static OFString XMLgetAllAttributeValues(XMLNode& fileNode, const OFString& attr)
{
OFString attributeValues;
#ifndef _XMLWIDECHAR
OFList<OFString> attributeValueslist;
- if (XMLsearchAttribute(fileNode, &attributeValueslist, attr))
+ if (XMLsearchAttribute(fileNode, attributeValueslist, attr))
{
- //If the Attribute is mediaType, initialize with text/xml to exclude
- //the primary MIME Type of the encapsulated document
+ // If the Attribute is mediaType, initialize with text/xml to exclude
+ // the primary MIME Type of the encapsulated document
if (attr == "mediaType") attributeValues.append("text/xml");
+
while (!attributeValueslist.empty())
{
if (attributeValues.find(attributeValueslist.front()) == OFString_npos)
}
attributeValueslist.pop_front();
}
- //remove the primary MIME Type of the
- //encapsulated document
+
+ // remove the primary MIME Type of the encapsulated document
if (attr == "mediaType")
{
if (attributeValues.size() > 9)
return attributeValues;
}
-OFString DcmEncapsulatedDocument::XMLgetAttribute(
- XMLNode fileNode,
- DcmTagKey attr)
+
+/** Retrieve the value from the CDA document corresponding to the given DICOM Tag,
+ * according to DICOM Part 20, section A.8.
+ * @param fileNode the root XML node.
+ * @param attr the tag to search for in the CDA file.
+ * @return OFstring containing the value of the corresponding tag.
+ */
+static OFString XMLgetAttribute(XMLNode& fileNode, const DcmTagKey& attr)
{
- OFString result = "";
#ifndef _XMLWIDECHAR
- if (attr == DCM_DocumentTitle)
- {
- if (fileNode.getChildNode("title").getText() != NULL)
+ if (attr == DCM_DocumentTitle)
{
- result = OFString(OFSTRING_GUARD(fileNode.getChildNode("title").getText()));
+ if (fileNode.getChildNode("title").getText() != NULL)
+ {
+ return OFString(OFSTRING_GUARD(fileNode.getChildNode("title").getText()));
+ }
}
- }
- if (attr == DCM_HL7InstanceIdentifier)
- {
- result = OFString(OFSTRING_GUARD(fileNode.getChildNode("id").getAttribute("root"))) + "^"
- + OFString(OFSTRING_GUARD(fileNode.getChildNode("id").getAttribute("extension")));
- }
- /*PatientNameExtension could reflect the type of name (PHON, IDE, ABC)
- if (attr == DCM_PatientNameExtension)
- {
- result = OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getAttribute("use")));
- }*/
- if (attr == DCM_PatientName)
- {
- result = OFString(
- OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/family").getText())) + "^"
- + OFString(OFSTRING_GUARD(
- fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode(
- "given", 0).getText())) + "^"
- + OFString(OFSTRING_GUARD(
- fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode(
- "given", 1).getText())) + "^"
- + OFString(
- OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/prefix").getText())) + "^"
- + OFString(
- OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/suffix").getText()));
- }
- if (attr == DCM_PatientSex)
- {
- result = OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath(
- "recordTarget/patientRole/patient/administrativeGenderCode").getAttribute("code")));
- }
- if (attr == DCM_PatientBirthDate)
- {
- result = OFString(OFSTRING_GUARD(
- fileNode.getChildNodeByPath("recordTarget/patientRole/patient/birthTime").getAttribute(
- "value")));
- }
- //Table A.8-1. Basic Code Attributes Mapping to HL7 V3 Code Data Types (CV, CS, CE and CD)
- if (attr == DCM_PatientID)
- {
- result = OFString(
- OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/id").getAttribute("extension")));
- }
- if (attr == DCM_CodeValue)//Code Value
- {
- result = OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("code")));
- }
- if (attr == DCM_CodingSchemeUID)//Coding Scheme UID (PS3.16)
- {
- result = OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystem")));
- }
- if (attr == DCM_CodingSchemeDesignator)//Coding Scheme Designator (0008,0102)
- {
- OFString CSDtemp = OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystemName")));
- // Abbreviate most common CSNs
- if (CSDtemp == OFString("LOINC"))
+
+ if (attr == DCM_HL7InstanceIdentifier)
{
- result = OFString("LN");
+ return OFString(OFSTRING_GUARD(fileNode.getChildNode("id").getAttribute("root"))) + "^"
+ + OFString(OFSTRING_GUARD(fileNode.getChildNode("id").getAttribute("extension")));
}
- else
+
+ if (attr == DCM_PatientName)
+ {
+ return OFString(
+ OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/family").getText())) + "^"
+ + OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode("given", 0).getText())) + "^"
+ + OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name").getChildNode("given", 1).getText())) + "^"
+ + OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/prefix").getText())) + "^"
+ + OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/name/suffix").getText()));
+ }
+
+ if (attr == DCM_PatientSex)
+ {
+ return OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/administrativeGenderCode").getAttribute("code")));
+ }
+
+ if (attr == DCM_PatientBirthDate)
+ {
+ return OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/patient/birthTime").getAttribute("value")));
+ }
+
+ //Table A.8-1. Basic Code Attributes Mapping to HL7 V3 Code Data Types (CV, CS, CE and CD)
+ if (attr == DCM_PatientID)
+ {
+ return OFString(OFSTRING_GUARD(fileNode.getChildNodeByPath("recordTarget/patientRole/id").getAttribute("extension")));
+ }
+
+ if (attr == DCM_CodeValue)
{
- if (CSDtemp == OFString("DICOM"))
+ return OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("code")));
+ }
+ if (attr == DCM_CodingSchemeUID)
+ {
+ return OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystem")));
+ }
+ if (attr == DCM_CodingSchemeDesignator)
+ {
+ OFString CSDtemp = OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystemName")));
+
+ // Abbreviate most common CSNs
+ if (CSDtemp == OFString("LOINC"))
{
- result = OFString("DC");
+ return OFString("LN");
}
else
{
- if (CSDtemp == OFString("SNOMED"))
+ if (CSDtemp == OFString("DICOM"))
{
- result = OFString("SRT");
+ return OFString("DCM");
}
else
{
- result = CSDtemp;
+ if (CSDtemp == OFString("SNOMED"))
+ {
+ return OFString("SCT");
+ }
+ else
+ {
+ return CSDtemp;
+ }
}
}
}
- }
- if (attr == DCM_CodingSchemeVersion)//Coding Scheme Version (0008,0103)
- {
- result = OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystemVersion")));
- }
- if (attr == DCM_CodeMeaning)//Code Meaning (0008,0104)
- {
- result = OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("displayName")));
- }
+
+ if (attr == DCM_CodingSchemeVersion)
+ {
+ return OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("codeSystemVersion")));
+ }
+
+ if (attr == DCM_CodeMeaning)
+ {
+ return OFString(OFSTRING_GUARD(fileNode.getChildNode("code").getAttribute("displayName")));
+ }
+
+ // this shouldn't happen
+ DCMDATA_ERROR("XMLgetAttribute called with unsupported attribute tag " << attr);
#endif
- return result;
+
+ return "";
}
-int DcmEncapsulatedDocument::getCDAData(
- const char *filename,
- OFLogger &appLogger)
+// ========== class methods ==========
+
+OFCondition DcmEncapsulatedDocument::getCDAData()
{
#ifdef _XMLWIDECHAR
#ifdef _MSC_VER
-#pragma message("DCMTK compiled with 'wide char XML parser'. cda2dcm will be unable to read and encapsulate CDA documents.")
+#pragma message("DCMTK compiled with 'wide char XML parser'. dcmencap will be unable to read and encapsulate CDA documents.")
#else
-#warning "DCMTK compiled with 'wide char XML parser'. cda2dcm will be unable to read and encapsulate CDA documents."
+#warning "DCMTK compiled with 'wide char XML parser'. dcmencap will be unable to read and encapsulate CDA documents."
#endif
- OFLOG_ERROR(appLogger, "DCMTK compiled with \"wide char XML parser\". Cannot parse CDA data because of incompatible API.");
- return 99;
+ DCMDATA_ERROR("DCMTK compiled with \"wide char XML parser\". Cannot parse CDA data because of incompatible API.");
+ return EC_XMLParseError;
#else
- if (ftype != "cda")
- {
- OFLOG_WARN(appLogger, "Filetype mismatch or filetype not set. Current ftype is " << ftype);
- }
- XMLResults err;
- XMLNode fileNode = XMLNode::parseFile(filename, "ClinicalDocument", &err);
- OFLOG_TRACE(appLogger, "checking if the XML file is correctly formatted");
- if (0 != err.error)
- {
- OFLOG_ERROR(appLogger, fileNode.getError(err.error));
- return EXITCODE_INVALID_INPUT_FILE;
- }
- else
- {
- OFLOG_TRACE(appLogger, "XML file is correctly formatted");
- }
- OFLOG_TRACE(appLogger, "Getting all media types from CDA file");
- cda_mediaTypes = XMLgetAllAttributeValues(fileNode, "mediaType");
- OFLOG_TRACE(appLogger, "Following mediaTypes were found: " << cda_mediaTypes);
- OFLOG_TRACE(appLogger, "Getting HL7 Instance Identifier from CDA file");
- hl7_InstanceIdentifier = XMLgetAttribute(fileNode, DCM_HL7InstanceIdentifier);
- OFLOG_TRACE(appLogger, "Reading and comparing patient information between CDA File and options");
- OFString pID = XMLgetAttribute(fileNode, DCM_PatientID);
- if ((pID != "") && (opt_patientID != pID))
- {
- if (opt_patientID != "")
+ DCMDATA_INFO("Extracting information from CDA document content");
+
+ XMLResults err;
+ XMLNode fileNode = XMLNode::parseFile(ifname_.c_str(), "ClinicalDocument", &err);
+ DCMDATA_TRACE("checking if the XML file is correctly formatted");
+ if (0 != err.error)
{
- //if no-override option is inactive, return an error
- if (!opt_override)
- {
- OFLOG_ERROR(appLogger, "Patient ID mismatch:" << OFendl
- << "Found in the CDA file : " << pID << OFendl
- << "Entered (or found in DCM file): " << opt_patientID << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- else
- {
- OFLOG_WARN(appLogger, "Patient ID mismatch:" << OFendl
- << "Found in the CDA file : " << pID << OFendl
- << "Provided (in DCM file): " << opt_patientID);
- }
+ DCMDATA_ERROR(fileNode.getError(err.error));
+ return EC_XMLParseError;
}
else
{
- opt_patientID = pID;
+ DCMDATA_TRACE("XML file is correctly formatted");
}
- }
- OFString pBirthDate = XMLgetAttribute(fileNode, DCM_PatientBirthDate);
- if ((pBirthDate != "") && (opt_patientBirthdate != pBirthDate))
- {
- if (opt_patientBirthdate != "")
+ DCMDATA_TRACE("Getting all media types from CDA file");
+ cda_mediaTypes = XMLgetAllAttributeValues(fileNode, "mediaType");
+ DCMDATA_TRACE("Following mediaTypes were found: " << cda_mediaTypes);
+ DCMDATA_TRACE("Getting HL7 Instance Identifier from CDA file");
+ hl7_InstanceIdentifier = XMLgetAttribute(fileNode, DCM_HL7InstanceIdentifier);
+ DCMDATA_TRACE("Reading and comparing patient information between CDA File and options");
+ OFString pID = XMLgetAttribute(fileNode, DCM_PatientID);
+ if ((pID.length() > 0) && (patientID_ != pID))
{
- if (!opt_override)
+ if (patientID_.length() > 0)
{
- OFLOG_ERROR(appLogger, "Patient Birth Date mismatch:" << OFendl
- << "Found in the CDA file : " << pBirthDate << OFendl
- << "Provided (in DCM file): " << opt_patientBirthdate << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
+ if (override_) DCMDATA_WARN("Patient ID mismatch: '" << pID << "' in CDA, '" << patientID_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("Patient ID mismatch: '" << pID << "' in CDA, '" << patientID_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
else
{
- OFLOG_WARN(appLogger, "Patient Birth Date mismatch:" << OFendl
- << "Found in the CDA file : " << pBirthDate << OFendl
- << "Provided (in DCM file): " << opt_patientBirthdate);
+ patientID_ = pID;
}
}
- else opt_patientBirthdate = pBirthDate;
- }
- OFString pSex = XMLgetAttribute(fileNode, DCM_PatientSex);
- if ((pSex != "") && (opt_patientSex != pSex))
- {
- if (opt_patientSex != "")
+ OFString pBirthDate = XMLgetAttribute(fileNode, DCM_PatientBirthDate);
+ if ((pBirthDate.length() > 0) && (patientBirthdate_ != pBirthDate))
{
- if (!opt_override)
- {
- OFLOG_ERROR(appLogger, "Patient Sex mismatch:" << OFendl
- << "Found in the CDA file : " << pSex << OFendl
- << "Provided (in DCM file): " << opt_patientSex << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- else
+ if (patientBirthdate_.length() > 0)
{
- OFLOG_WARN(appLogger, "Patient Sex mismatch:" << OFendl
- << "Found in the CDA file : " << pSex << OFendl
- << "Provided (in DCM file): " << opt_patientSex);
+ if (override_) DCMDATA_WARN("Patient Birth Date mismatch: '" << pBirthDate << "' in CDA, '" << patientBirthdate_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("Patient Birth Date mismatch: '" << pBirthDate << "' in CDA, '" << patientBirthdate_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
+ else patientBirthdate_ = pBirthDate;
}
- else opt_patientSex = pSex;
- }
- OFString pName = XMLgetAttribute(fileNode, DCM_PatientName);
- if ((pName != "^^^^") && (opt_patientName != pName))
- {
- if (opt_patientName != "")
+ OFString pSex = XMLgetAttribute(fileNode, DCM_PatientSex);
+ if ((pSex.length() > 0) && (patientSex_ != pSex))
{
- if (!opt_override)
- {
- OFLOG_ERROR(appLogger, "Patient Name mismatch:" << OFendl
- << "Found in the CDA file : " << pName << OFendl
- << "Provided (in DCM file): " << opt_patientName << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- else
+ if (patientSex_.length() > 0)
{
- OFLOG_WARN(appLogger, "Patient Name mismatch:" << OFendl
- << "Found in the CDA file : " << pName << OFendl
- << "Provided (in DCM file): " << opt_patientName);
+ if (override_) DCMDATA_WARN("Patient Sex mismatch: '" << pSex << "' in CDA, '" << patientSex_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("Patient Sex mismatch: '" << pSex << "' in CDA, '" << patientSex_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
+ else patientSex_ = pSex;
}
- else opt_patientName = pName;
- }
- //get document title from CDA
- OFString dTitle = XMLgetAttribute(fileNode, DCM_DocumentTitle);
- if (opt_documentTitle == "")
- {
- if (opt_conceptCSD != "") opt_documentTitle = opt_conceptCSD;
- if (opt_conceptCV != "") opt_documentTitle = opt_conceptCV;
- if (opt_conceptCM != "") opt_documentTitle = opt_conceptCM;
- }
-
- if ((dTitle != "") && (opt_documentTitle != dTitle))
- {
- if (opt_documentTitle != "")
+ OFString pName = XMLgetAttribute(fileNode, DCM_PatientName);
+ if ((pName != "^^^^") && (patientName_ != pName))
{
- if (!opt_override)
+ if (patientName_.length() > 0)
{
- OFLOG_ERROR(appLogger, "Document Title mismatch:" << OFendl
- << "Found in the CDA file : " << dTitle << OFendl
- << "Provided (in DCM file): " << opt_documentTitle << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- else
- {
- OFLOG_WARN(appLogger, "Document Title mismatch:" << OFendl
- << "Found in the CDA file : " << dTitle << OFendl
- << "Provided (in DCM file): " << opt_documentTitle);
+ if (override_) DCMDATA_WARN("Patient Name mismatch: '" << pName << "' in CDA, '" << patientName_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("Patient Name mismatch: '" << pName << "' in CDA, '" << patientName_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
+ else patientName_ = pName;
}
- else opt_documentTitle = dTitle;
- }
- //get Concept information from CDA
- OFString cCSD = XMLgetAttribute(fileNode, DCM_CodingSchemeDesignator);
- if ((cCSD != "") && (opt_conceptCSD != cCSD))
- {
- if (opt_conceptCSD != "")
+ //get document title from CDA
+ OFString dTitle = XMLgetAttribute(fileNode, DCM_DocumentTitle);
+ if ((dTitle.length() > 0) && (documentTitle_ != dTitle))
{
- if (!opt_override)
+ if (documentTitle_.length() > 0)
{
- OFLOG_ERROR(appLogger, "concept CSD mismatch:" << OFendl
- << "Found in the CDA file : " << cCSD << OFendl
- << "Provided (in DCM file): " << opt_conceptCSD << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- else
- {
- OFLOG_WARN(appLogger, "concept CSD mismatch:" << OFendl
- << "Found in the CDA file : " << cCSD << OFendl
- << "Provided (in DCM file): " << opt_conceptCSD);
+ if (override_) DCMDATA_WARN("Document Title mismatch: '" << dTitle << "' in CDA, '" << documentTitle_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("Document Title mismatch: '" << dTitle << "' in CDA, '" << documentTitle_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
+ else documentTitle_ = dTitle;
}
- else opt_conceptCSD = cCSD;
- }
- OFString cCV = XMLgetAttribute(fileNode, DCM_CodeValue);
- if ((cCV != "") && (opt_conceptCV != cCV))
- {
- if (opt_conceptCV != "")
+
+ //get Concept information from CDA
+ OFString cCSD = XMLgetAttribute(fileNode, DCM_CodingSchemeDesignator);
+ if ((cCSD.length() > 0) && (conceptCSD_ != cCSD))
{
- if (!opt_override)
- {
- OFLOG_ERROR(appLogger, "concept CV mismatch:" << OFendl
- << "Found in the CDA file : " << cCV << OFendl
- << "Provided (in DCM file): " << opt_conceptCV << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
- }
- else
+ if (conceptCSD_.length() > 0)
{
- OFLOG_WARN(appLogger, "concept CV mismatch:" << OFendl
- << "Found in the CDA file : " << cCV << OFendl
- << "Provided (in DCM file): " << opt_conceptCV);
+ if (override_) DCMDATA_WARN("concept CSD mismatch: '" << cCSD << "' in CDA, '" << conceptCSD_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("concept CSD mismatch: '" << cCSD << "' in CDA, '" << conceptCSD_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
+ else conceptCSD_ = cCSD;
}
- else opt_conceptCV = cCV;
- }
- OFString cCM = XMLgetAttribute(fileNode, DCM_CodeMeaning);
- if ((cCM != "") && (opt_conceptCM != cCM))
- {
- if (opt_conceptCM != "")
+ OFString cCV = XMLgetAttribute(fileNode, DCM_CodeValue);
+ if ((cCV.length() > 0) && (conceptCV_ != cCV))
{
- if (!opt_override)
+ if (conceptCV_.length() > 0)
{
- OFLOG_ERROR(appLogger, "concept CM mismatch:" << OFendl
- << "Found in the CDA file : " << cCM << OFendl
- << "Provided (in DCM file): " << opt_conceptCM << OFendl
- << "If you wish to override, run again with +ov");
- return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
+ if (override_) DCMDATA_WARN("concept CV mismatch: '" << cCV << "' in CDA, '" << conceptCV_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("concept CV mismatch: '" << cCV << "' in CDA, '" << conceptCV_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
- else
+ else conceptCV_ = cCV;
+ }
+ OFString cCM = XMLgetAttribute(fileNode, DCM_CodeMeaning);
+ if ((cCM.length() > 0) && (conceptCM_ != cCM))
+ {
+ if (conceptCM_.length() > 0)
{
- OFLOG_WARN(appLogger, "concept CM mismatch:" << OFendl
- << "Found in the CDA file : " << cCM << OFendl
- << "Provided (in DCM file): " << opt_conceptCM);
+ if (override_) DCMDATA_WARN("concept CM mismatch: '" << cCM << "' in CDA, '" << conceptCM_ << "' in DICOM file or specified via command line.");
+ else
+ {
+ DCMDATA_ERROR("concept CM mismatch: '" << cCM << "' in CDA, '" << conceptCM_ << "' in DICOM file or specified via command line.");
+ return EC_InvalidValue;
+ }
}
+ else conceptCM_ = cCM;
}
- else opt_conceptCM = cCM;
- }
- return EXITCODE_NO_ERROR;
+ return EC_Normal;
#endif
}
-void DcmEncapsulatedDocument::addCDACommandlineOptions(OFCommandLine &cmd)
-{
- ftype = "cda";
- cmd.setOptionColumns(LONGCOL, SHORTCOL);
- cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
- cmd.addParam("cdafile-in", "CDA input filename to be converted");
- cmd.addParam("dcmfile-out", "DICOM output filename (\"-\" for stdout)");
- addGeneralOptions(cmd);
- addDocumentOptions(cmd);
- cmd.addSubGroup("override CDA data:");
- cmd.addOption("--no-override", "-ov",
- "CDA patient and document data must match study,\nseries or manually entered information (default)");
- cmd.addOption("--override", "+ov",
- "CDA's data will be overwritten by study, series\nor manually entered information");
- addOutputOptions(cmd);
-}
-void DcmEncapsulatedDocument::addPDFCommandlineOptions(OFCommandLine &cmd)
+static void addGeneralOptions(OFCommandLine &cmd)
{
- ftype = "pdf";
- cmd.setOptionColumns(LONGCOL, SHORTCOL);
- cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
- cmd.addParam("pdffile-in", "PDF input filename to be converted");
- cmd.addParam("dcmfile-out", "DICOM output filename (\"-\" for stdout)");
- addGeneralOptions(cmd);
- addDocumentOptions(cmd);
- addOutputOptions(cmd);
+ cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2);
+ cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive);
+ cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive);
+ OFLog::addOptions(cmd);
}
-void DcmEncapsulatedDocument::addSTLCommandlineOptions(OFCommandLine &cmd)
-{
- ftype = "stl";
- cmd.setOptionColumns(LONGCOL, SHORTCOL);
- cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
- cmd.addParam("stlfile-in", "STL input filename to be converted");
- cmd.addParam("dcmfile-out", "DICOM output filename (\"-\" for stdout)");
- addGeneralOptions(cmd);
- addDocumentOptions(cmd);
- cmd.addSubGroup("enhanced general equipment:");
- cmd.addOption("--manufacturer", "+mn", 1, "[n]ame: string",
- "manufacturer's name");
- cmd.addOption("--manufacturer-model", "+mm", 1, "[n]ame: string",
- "manufacturer's model name");
- cmd.addOption("--device-serial", "+ds", 1, "[n]umber: string",
- "device serial number");
- cmd.addOption("--software-versions", "+sv", 1, "[v]ersions: string",
- "software versions");
- cmd.addSubGroup("3d model measurement units:");
- cmd.addOption("--measurement-units", "+mu", 3, "[CSD] [CV] [CM]: string (default: UCUM, um, um)",
- "measurement units defined by coding scheme\ndesignator CSD, code value CV, code meaning CM");
- addOutputOptions(cmd);
-}
-void DcmEncapsulatedDocument::addGeneralOptions(OFCommandLine &cmd)
+static void addDocumentOptions(OFCommandLine &cmd)
{
- cmd.addGroup("general options:", LONGCOL, SHORTCOL + 2);
- cmd.addOption("--help", "-h", "print this help text and exit", OFCommandLine::AF_Exclusive);
- cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive);
- OFLog::addOptions(cmd);
+ cmd.addGroup("DICOM document options:");
+
+ cmd.addSubGroup("document title:");
+ cmd.addOption("--title", "+t", 1, "[t]itle: string (default: empty)", "document title");
+ cmd.addOption("--concept-name", "+cn", 3, "[CSD] [CV] [CM]: string (default: empty)",
+ "coded representation of document title defined\nby coding scheme designator CSD,\n"
+ "code value CV and code meaning CM");
+ cmd.addSubGroup("patient data:");
+ cmd.addOption("--patient-name", "+pn", 1, "[n]ame: string", "patient's name in DICOM PN syntax");
+ cmd.addOption("--patient-id", "+pi", 1, "[i]d: string", "patient identifier");
+ cmd.addOption("--patient-birthdate", "+pb", 1, "[d]ate: string (YYYYMMDD)", "patient's birth date");
+ cmd.addOption("--patient-sex", "+ps", 1, "[s]ex: string (M, F or O)", "patient's sex");
+
+ cmd.addSubGroup("device data:");
+ cmd.addOption("--manufacturer", "+mn", 1, "[n]ame: string", "manufacturer's name");
+ cmd.addOption("--manufacturer-model", "+mm", 1, "[n]ame: string", "manufacturer's model name");
+ cmd.addOption("--device-serial", "+ds", 1, "[n]umber: string", "device serial number");
+ cmd.addOption("--software-versions", "+sv", 1, "[v]ersions: string", "software versions");
+
+ cmd.addSubGroup("manufacturing 3d model data (STL/MTL/OBJ only):");
+ cmd.addOption("--measurement-units", "+mu", 3, "[CSD] [CV] [CM]: string (default: UCUM, um, um)",
+ "measurement units defined by coding scheme\ndesignator CSD, code value CV, code meaning CM");
+
+ cmd.addSubGroup("study and series:");
+ cmd.addOption("--generate", "+sg", "generate new study and\nseries UIDs (default)");
+ cmd.addOption("--study-from", "+st", 1, "[f]ilename: string", "read patient/study data from DICOM file");
+ cmd.addOption("--series-from", "+se", 1, "[f]ilename: string", "read patient/study/series data from DICOM file");
+
+ cmd.addSubGroup("instance number:");
+ cmd.addOption("--instance-one", "+i1", "use instance number 1\n(default, not with +se)");
+ cmd.addOption("--instance-inc", "+ii", "increment instance number (only with +se)");
+ cmd.addOption("--instance-set", "+is", 1, "[i]nstance number: integer", "use instance number i");
+
+ cmd.addSubGroup("burned-in annotation:");
+ cmd.addOption("--annotation-yes", "+an", "document contains patient identifying data\n(default)");
+ cmd.addOption("--annotation-no", "-an", "document does not contain patient identif. data");
}
-void DcmEncapsulatedDocument::addDocumentOptions(OFCommandLine &cmd)
+
+static void addOutputOptions(OFCommandLine &cmd)
{
- cmd.addGroup("DICOM document options:");
- cmd.addSubGroup("document title:");
- cmd.addOption("--title", "+t", 1, "[t]itle: string (default: empty)",
- "document title");
- cmd.addOption("--concept-name", "+cn", 3, "[CSD] [CV] [CM]: string (default: empty)",
- "coded representation of document title defined\nby coding scheme designator CSD,\n"
- "code value CV and code meaning CM");
- cmd.addSubGroup("patient data:");
- cmd.addOption("--patient-name", "+pn", 1, "[n]ame: string",
- "patient's name in DICOM PN syntax");
- cmd.addOption("--patient-id", "+pi", 1, "[i]d: string",
- "patient identifier");
- cmd.addOption("--patient-birthdate", "+pb", 1, "[d]ate: string (YYYYMMDD)",
- "patient's birth date");
- cmd.addOption("--patient-sex", "+ps", 1, "[s]ex: string (M, F or O)",
- "patient's sex");
- cmd.addSubGroup("study and series:");
- cmd.addOption("--generate", "+sg", "generate new study and\nseries UIDs (default)");
- cmd.addOption("--study-from", "+st", 1, "[f]ilename: string",
- "read patient/study data from DICOM file");
- cmd.addOption("--series-from", "+se", 1, "[f]ilename: string",
- "read patient/study/series data from DICOM file");
- cmd.addSubGroup("instance number:");
- cmd.addOption("--instance-one", "+i1", "use instance number 1\n(default, not with +se)");
- cmd.addOption("--instance-inc", "+ii", "increment instance number (only with +se)");
- cmd.addOption("--instance-set", "+is", 1, "[i]nstance number: integer", "use instance number i");
- cmd.addSubGroup("burned-in annotation:");
- cmd.addOption("--annotation-yes", "+an", "document contains patient identifying data\n(default)");
- cmd.addOption("--annotation-no", "-an", "document does not contain patient identif. data");
+ cmd.addGroup("processing options:");
+ cmd.addSubGroup("CDA processing options:");
+ cmd.addOption("--no-override", "-ov", "CDA patient and document data must match study,\nseries or manually entered information (default)");
+ cmd.addOption("--override", "+ov", "CDA's data will be overwritten by study, series\nor manually entered information");
+
+ cmd.addSubGroup("other processing options:");
+ cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\", path or dict. name=\"str\"", "add further attribute");
+
+ cmd.addGroup("output options:");
+
+ cmd.addSubGroup("output transfer syntax:");
+ cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian (default)");
+ cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS");
+ cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS");
+
+ cmd.addSubGroup("group length encoding:");
+ cmd.addOption("--group-length-remove", "-g", "write without group length elements (default)");
+ cmd.addOption("--group-length-create", "+g", "write with group length elements");
+
+ cmd.addSubGroup("length encoding in sequences and items:");
+ cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)");
+ cmd.addOption("--length-undefined", "-e", "write with undefined lengths");
+
+ cmd.addSubGroup("data set trailing padding (not with --write-dataset):");
+ cmd.addOption("--padding-retain", "-p=", "do not change padding (default)");
+ cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)");
+ cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer",
+ "align file on multiple of f bytes\nand items on multiple of i bytes");
}
-void DcmEncapsulatedDocument::addOutputOptions(OFCommandLine &cmd)
+
+void DcmEncapsulatedDocument::addCommandlineOptions(OFCommandLine &cmd) const
{
- cmd.addGroup("processing options:");
- cmd.addSubGroup("other processing options:");
- cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\", path or dict. name=\"str\"",
- "add further attribute");
- cmd.addGroup("output options:");
- cmd.addSubGroup("output transfer syntax:");
- cmd.addOption("--write-xfer-little", "+te", "write with explicit VR little endian (default)");
- cmd.addOption("--write-xfer-big", "+tb", "write with explicit VR big endian TS");
- cmd.addOption("--write-xfer-implicit", "+ti", "write with implicit VR little endian TS");
- cmd.addSubGroup("group length encoding:");
- cmd.addOption("--group-length-recalc", "+g=", "recalculate group lengths if present (default)");
- cmd.addOption("--group-length-create", "+g", "always write with group length elements");
- cmd.addOption("--group-length-remove", "-g", "always write without group length elements");
- cmd.addSubGroup("length encoding in sequences and items:");
- cmd.addOption("--length-explicit", "+e", "write with explicit lengths (default)");
- cmd.addOption("--length-undefined", "-e", "write with undefined lengths");
- cmd.addSubGroup("data set trailing padding (not with --write-dataset):");
- cmd.addOption("--padding-retain", "-p=", "do not change padding (default)");
- cmd.addOption("--padding-off", "-p", "no padding (implicit if --write-dataset)");
- cmd.addOption("--padding-create", "+p", 2, "[f]ile-pad [i]tem-pad: integer",
- "align file on multiple of f bytes\nand items on multiple of i bytes");
+ cmd.setOptionColumns(LONGCOL, SHORTCOL);
+ cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
+ cmd.addParam("docfile-in", "input filename to be converted");
+ cmd.addParam("dcmfile-out", "DICOM output filename (\"-\" for stdout)");
+
+ addGeneralOptions(cmd);
+
+ cmd.addGroup("input options:", LONGCOL, SHORTCOL + 2);
+ cmd.addSubGroup("input file format options:");
+ cmd.addOption("--filetype-auto", "+fa", "automatically determine file type (default)");
+ cmd.addOption("--filetype-pdf", "+fp", "expect PDF file");
+ cmd.addOption("--filetype-cda", "+fc", "expect CDA file");
+ cmd.addOption("--filetype-stl", "+fs", "expect STL file");
+ cmd.addOption("--filetype-mtl", "+fm", "expect MTL file");
+ cmd.addOption("--filetype-obj", "+fo", "expect OBJ file");
+
+ addDocumentOptions(cmd);
+
+ addOutputOptions(cmd);
}
+
void DcmEncapsulatedDocument::parseArguments(
OFConsoleApplication &app,
OFCommandLine &cmd)
{
- //command line parameters and options
- cmd.getParam(1, opt_ifname);
- cmd.getParam(2, opt_ofname);
-
- OFLog::configureFromCommandLine(cmd, app);
-
- dcmEnableGenerationOfNewVRs();
+ //command line parameters and options
+ cmd.getParam(1, ifname_);
+ cmd.getParam(2, ofname_);
- // Override keys are applied at the very end of the conversion "pipeline"
- OFList<OFString> overrideKeys;
+ // ---------- parse general options ----------
+ OFLog::configureFromCommandLine(cmd, app);
- cmd.beginOptionBlock();
- if (cmd.findOption("--generate"))
- {
- opt_seriesFile = "";
- opt_readSeriesInfo = OFFalse;
- }
+ // ---------- parse input file format options ----------
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--filetype-auto")) ftype_ = DT_unknownDocument;
+ if (cmd.findOption("--filetype-pdf")) ftype_ = DT_pdfDocument;
+ if (cmd.findOption("--filetype-cda")) ftype_ = DT_cdaDocument;
+ if (cmd.findOption("--filetype-stl")) ftype_ = DT_stlDocument;
+ if (cmd.findOption("--filetype-mtl")) ftype_ = DT_mtlDocument;
+ if (cmd.findOption("--filetype-obj")) ftype_ = DT_objDocument;
+ cmd.endOptionBlock();
- if (cmd.findOption("--series-from"))
- {
- app.checkValue(cmd.getValue(opt_seriesFile));
- opt_readSeriesInfo = OFTrue;
- }
+ // ---------- parse document options ----------
- if (cmd.findOption("--study-from"))
- {
- app.checkValue(cmd.getValue(opt_seriesFile));
- opt_readSeriesInfo = OFFalse;
- }
- cmd.endOptionBlock();
- if (cmd.findOption("--title"))
- {
- app.checkValue(cmd.getValue(opt_documentTitle));
- }
- if (cmd.findOption("--concept-name"))
- {
- app.checkValue(cmd.getValue(opt_conceptCSD));
- app.checkValue(cmd.getValue(opt_conceptCV));
- app.checkValue(cmd.getValue(opt_conceptCM));
- }
- if (cmd.findOption("--patient-name"))
- {
- app.checkValue(cmd.getValue(opt_patientName));
- app.checkConflict("--patient-name", "--study-from or --series-from",
- opt_seriesFile != "");
- }
- if (cmd.findOption("--patient-id"))
- {
- app.checkValue(cmd.getValue(opt_patientID));
- app.checkConflict("--patient-id", "--study-from or --series-from",
- opt_seriesFile != "");
- }
- if (cmd.findOption("--patient-birthdate"))
- {
- app.checkValue(cmd.getValue(opt_patientBirthdate));
- app.checkConflict("--patient-birthdate", "--study-from or --series-from", opt_seriesFile != "");
- }
- if (cmd.findOption("--patient-sex"))
- {
- app.checkValue(cmd.getValue(opt_patientSex));
- app.checkConflict("--patient-sex", "--study-from or --series-from", opt_seriesFile != "");
- }
- cmd.beginOptionBlock();
- if (cmd.findOption("--annotation-yes"))
- {
- opt_annotation = OFTrue;
- }
- if (cmd.findOption("--annotation-no"))
- {
- opt_annotation = OFFalse;
- }
- cmd.endOptionBlock();
- if (ftype == "cda")
- {
cmd.beginOptionBlock();
- if (cmd.findOption("--override"))
+ if (cmd.findOption("--generate"))
{
- opt_override = OFTrue;
+ seriesFile_ = "";
+ readSeriesInfo_ = OFFalse;
}
- if (cmd.findOption("--no-override"))
+
+ if (cmd.findOption("--series-from"))
{
- opt_override = OFFalse;
+ app.checkValue(cmd.getValue(seriesFile_));
+ readSeriesInfo_ = OFTrue;
+ }
+
+ if (cmd.findOption("--study-from"))
+ {
+ app.checkValue(cmd.getValue(seriesFile_));
+ readSeriesInfo_ = OFFalse;
}
cmd.endOptionBlock();
- }
- if (ftype == "stl")
- {
- if (cmd.findOption("--measurement-units"))
+
+ if (cmd.findOption("--title"))
{
- app.checkValue(cmd.getValue(opt_measurementUnitsCSD));
- app.checkValue(cmd.getValue(opt_measurementUnitsCV));
- app.checkValue(cmd.getValue(opt_measurementUnitsCM));
+ app.checkValue(cmd.getValue(documentTitle_));
+ }
+ if (cmd.findOption("--concept-name"))
+ {
+ app.checkValue(cmd.getValue(conceptCSD_));
+ app.checkValue(cmd.getValue(conceptCV_));
+ app.checkValue(cmd.getValue(conceptCM_));
+ }
+ if (cmd.findOption("--patient-name"))
+ {
+ app.checkValue(cmd.getValue(patientName_));
+ app.checkConflict("--patient-name", "--study-from or --series-from", seriesFile_.length() > 0);
+ }
+ if (cmd.findOption("--patient-id"))
+ {
+ app.checkValue(cmd.getValue(patientID_));
+ app.checkConflict("--patient-id", "--study-from or --series-from", seriesFile_.length() > 0);
+ }
+ if (cmd.findOption("--patient-birthdate"))
+ {
+ app.checkValue(cmd.getValue(patientBirthdate_));
+ app.checkConflict("--patient-birthdate", "--study-from or --series-from", seriesFile_.length() > 0);
+ }
+ if (cmd.findOption("--patient-sex"))
+ {
+ app.checkValue(cmd.getValue(patientSex_));
+ app.checkConflict("--patient-sex", "--study-from or --series-from", seriesFile_.length() > 0);
}
- if (cmd.findOption("--manufacturer")) app.checkValue(cmd.getValue(opt_manufacturer));
- if (cmd.findOption("--manufacturer-model")) app.checkValue(cmd.getValue(opt_manufacturerModelName));
- if (cmd.findOption("--device-serial")) app.checkValue(cmd.getValue(opt_deviceSerialNumber));
- if (cmd.findOption("--software-versions")) app.checkValue(cmd.getValue(opt_softwareVersions));
- }
- cmd.beginOptionBlock();
- if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit;
- if (cmd.findOption("--write-xfer-big")) opt_oxfer = EXS_BigEndianExplicit;
- if (cmd.findOption("--write-xfer-implicit")) opt_oxfer = EXS_LittleEndianImplicit;
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--group-length-recalc")) opt_oglenc = EGL_recalcGL;
- if (cmd.findOption("--group-length-create")) opt_oglenc = EGL_withGL;
- if (cmd.findOption("--group-length-remove")) opt_oglenc = EGL_withoutGL;
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--length-explicit")) opt_oenctype = EET_ExplicitLength;
- if (cmd.findOption("--length-undefined")) opt_oenctype = EET_UndefinedLength;
- cmd.endOptionBlock();
-
- cmd.beginOptionBlock();
- if (cmd.findOption("--padding-retain"))
- {
- app.checkConflict("--padding-retain", "--write-dataset",
- opt_writeMode == EWM_dataset);
- opt_opadenc = EPD_noChange;
- }
- if (cmd.findOption("--padding-off")) opt_opadenc = EPD_withoutPadding;
- if (cmd.findOption("--padding-create"))
- {
- app.checkConflict("--padding-create", "--write-dataset",
- opt_writeMode == EWM_dataset);
- app.checkValue(cmd.getValueAndCheckMin(opt_filepad, 0));
- app.checkValue(cmd.getValueAndCheckMin(opt_itempad, 0));
- opt_opadenc = EPD_withPadding;
- }
- cmd.endOptionBlock();
- // create override attribute dataset (copied from findscu code)
- if (cmd.findOption("--key", 0, OFCommandLine::FOM_FirstFromLeft))
- {
- const char *ovKey = NULL;
- do
+ // initialize default for --series-from
+ if (seriesFile_.length() > 0 && readSeriesInfo_) increment_ = OFTrue;
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--instance-one"))
{
- app.checkValue(cmd.getValue(ovKey));
- overrideKeys.push_back(ovKey);
- } while (cmd.findOption("--key", 0, OFCommandLine::FOM_NextFromLeft));
- }
- DcmEncapsulatedDocument::setOverrideKeys(overrideKeys);
- // initialize default for --series-from
- if (opt_seriesFile != "" && opt_readSeriesInfo) opt_increment = OFTrue;
+ app.checkConflict("--instance-one", "--series-from", (seriesFile_.length() > 0) && readSeriesInfo_);
+ increment_ = OFFalse;
+ instance_ = 1;
+ }
+ if (cmd.findOption("--instance-inc"))
+ {
+ app.checkDependence("--instance-inc", "--series-from", (seriesFile_.length() > 0) && readSeriesInfo_);
+ increment_ = OFTrue;
+ }
+ if (cmd.findOption("--instance-set"))
+ {
+ increment_ = OFFalse;
+ app.checkValue(cmd.getValueAndCheckMin(instance_, 1));
+ }
+ cmd.endOptionBlock();
- cmd.beginOptionBlock();
- if (cmd.findOption("--instance-one"))
- {
- app.checkConflict("--instance-one", "--series-from",
- (opt_seriesFile != "") && opt_readSeriesInfo);
- opt_increment = OFFalse;
- opt_instance = 1;
- }
- if (cmd.findOption("--instance-inc"))
- {
- app.checkDependence("--instance-inc", "--series-from",
- (opt_seriesFile != "") && opt_readSeriesInfo);
- opt_increment = OFTrue;
- }
- if (cmd.findOption("--instance-set"))
- {
- opt_increment = OFFalse;
- app.checkValue(cmd.getValueAndCheckMin(opt_instance, 1));
- }
- cmd.endOptionBlock();
-}
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--annotation-yes"))
+ {
+ annotation_ = OFTrue;
+ }
+ if (cmd.findOption("--annotation-no"))
+ {
+ annotation_ = OFFalse;
+ }
+ cmd.endOptionBlock();
-OFCondition DcmEncapsulatedDocument::createIdentifiers(OFLogger &appLogger)
-{
- char buf[100];
- OFCondition cond = EC_Normal;
- Sint32 incrementedInstance = 0;
- if (opt_seriesFile != "")
- {
- DcmFileFormat dfile;
- cond = dfile.loadFile(opt_seriesFile, EXS_Unknown, EGL_noChange);
- if (cond.bad())
+ // ---------- parse CDA processing options ----------
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--override"))
{
- OFLOG_WARN(appLogger, cond.text()
- << ": reading file: " << opt_seriesFile);
+ app.checkConflict("--override", "--filetype-pdf", ftype_ == DT_pdfDocument);
+ app.checkConflict("--override", "--filetype-stl", ftype_ == DT_stlDocument);
+ app.checkConflict("--override", "--filetype-stl", ftype_ == DT_mtlDocument);
+ app.checkConflict("--override", "--filetype-stl", ftype_ == DT_objDocument);
+ override_ = OFTrue;
}
- else
+ if (cmd.findOption("--no-override"))
{
- const char *c = NULL;
+ app.checkConflict("--no-override", "--filetype-pdf", ftype_ == DT_pdfDocument);
+ app.checkConflict("--no-override", "--filetype-stl", ftype_ == DT_stlDocument);
+ app.checkConflict("--no-override", "--filetype-stl", ftype_ == DT_mtlDocument);
+ app.checkConflict("--no-override", "--filetype-stl", ftype_ == DT_objDocument);
+ override_ = OFFalse;
+ }
+ cmd.endOptionBlock();
+
+ // ---------- parse device data options ----------
+
+ if (cmd.findOption("--manufacturer"))
+ {
+ app.checkValue(cmd.getValue(manufacturer_));
+ }
+ if (cmd.findOption("--manufacturer-model"))
+ {
+ app.checkValue(cmd.getValue(manufacturerModelName_));
+ }
+ if (cmd.findOption("--device-serial"))
+ {
+ app.checkValue(cmd.getValue(deviceSerialNumber_));
+ }
+ if (cmd.findOption("--software-versions"))
+ {
+ app.checkValue(cmd.getValue(softwareVersions_));
+ }
+
+ // ---------- parse STL processing options ----------
+
+ if (cmd.findOption("--measurement-units"))
+ {
+ app.checkConflict("--measurement-units", "--filetype-cda", ftype_ == DT_cdaDocument);
+ app.checkConflict("--measurement-units", "--filetype-pdf", ftype_ == DT_pdfDocument);
+ app.checkValue(cmd.getValue(measurementUnitsCSD_));
+ app.checkValue(cmd.getValue(measurementUnitsCV_));
+ app.checkValue(cmd.getValue(measurementUnitsCM_));
+ }
+
+ // ---------- parse input file format options ----------
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--write-xfer-little")) oxfer_ = EXS_LittleEndianExplicit;
+ if (cmd.findOption("--write-xfer-big")) oxfer_ = EXS_BigEndianExplicit;
+ if (cmd.findOption("--write-xfer-implicit")) oxfer_ = EXS_LittleEndianImplicit;
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--group-length-remove")) oglenc_ = EGL_withoutGL;
+ if (cmd.findOption("--group-length-create")) oglenc_ = EGL_withGL;
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--length-explicit")) oenctype_ = EET_ExplicitLength;
+ if (cmd.findOption("--length-undefined")) oenctype_ = EET_UndefinedLength;
+ cmd.endOptionBlock();
+
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--padding-retain"))
+ {
+ app.checkConflict("--padding-retain", "--write-dataset",
+ writeMode_ == EWM_dataset);
+ opadenc_ = EPD_noChange;
+ }
+ if (cmd.findOption("--padding-off")) opadenc_ = EPD_withoutPadding;
+ if (cmd.findOption("--padding-create"))
+ {
+ app.checkConflict("--padding-create", "--write-dataset",
+ writeMode_ == EWM_dataset);
+ app.checkValue(cmd.getValueAndCheckMin(filepad_, 0));
+ app.checkValue(cmd.getValueAndCheckMin(itempad_, 0));
+ opadenc_ = EPD_withPadding;
+ }
+ cmd.endOptionBlock();
+
+ // create override attribute dataset
+ overrideKeys_.clear();
+ if (cmd.findOption("--key", 0, OFCommandLine::FOM_FirstFromLeft))
+ {
+ const char *ovKey = NULL;
+ do
+ {
+ app.checkValue(cmd.getValue(ovKey));
+ overrideKeys_.push_back(ovKey);
+ } while (cmd.findOption("--key", 0, OFCommandLine::FOM_NextFromLeft));
+ }
+
+}
+
+
+OFCondition DcmEncapsulatedDocument::createIdentifiers()
+{
+ char buf[100];
+ OFCondition cond = EC_Normal;
+ Sint32 incrementedInstance = 0;
+ if (seriesFile_.length() > 0)
+ {
+ DCMDATA_DEBUG("Reading series file");
+ DcmFileFormat dfile;
+ cond = dfile.loadFile(seriesFile_, EXS_Unknown, EGL_noChange);
+
+ if (cond.good())
+ {
+ const char *c = NULL;
DcmDataset *dset = dfile.getDataset();
if (dset)
{
- OFLOG_TRACE(appLogger, "reading patient attributes");
+ DCMDATA_TRACE("reading patient attributes");
c = NULL;
if (dset->findAndGetString(DCM_PatientName, c).good() && c)
{
- opt_patientName = c;
+ patientName_ = c;
}
c = NULL;
if (dset->findAndGetString(DCM_PatientID, c).good() && c)
{
- opt_patientID = c;
+ patientID_ = c;
}
c = NULL;
if (dset->findAndGetString(DCM_PatientBirthDate, c).good() && c)
{
- opt_patientBirthdate = c;
+ patientBirthdate_ = c;
}
c = NULL;
if (dset->findAndGetString(DCM_PatientSex, c).good() && c)
{
- opt_patientSex = c;
+ patientSex_ = c;
}
- OFLOG_TRACE(appLogger, "reading study attributes");
+ DCMDATA_TRACE("reading study attributes");
c = NULL;
if (dset->findAndGetString(DCM_StudyInstanceUID, c).good() && c)
{
- opt_studyUID = c;
+ studyUID_ = c;
+ }
+ c = NULL;
+ if (dset->findAndGetString(DCM_SpecificCharacterSet, c).good() && c)
+ {
+ specificCharSet_ = c;
}
- OFLOG_TRACE(appLogger, "reading series attributes");
- if (opt_readSeriesInfo)
+ DCMDATA_TRACE("reading series attributes");
+ if (readSeriesInfo_)
{
c = NULL;
if (dset->findAndGetString(DCM_SeriesInstanceUID, c).good() && c)
{
- opt_seriesUID = c;
+ seriesUID_ = c;
+ }
+ c = NULL;
+ if (dset->findAndGetString(DCM_Modality, c).good() && c)
+ {
+ modality_ = c;
}
if (dset->findAndGetSint32(DCM_InstanceNumber,
incrementedInstance).good())
{
incrementedInstance = 0;
}
- if (opt_increment) opt_instance = incrementedInstance;
+ if (increment_) instance_ = incrementedInstance;
+ }
+
+ DCMDATA_TRACE("reading reading device attributes");
+ c = NULL;
+ if (dset->findAndGetString(DCM_Manufacturer, c).good() && c)
+ {
+ manufacturer_ = c;
+ }
+ c = NULL;
+ if (dset->findAndGetString(DCM_ManufacturerModelName, c).good() && c)
+ {
+ manufacturerModelName_ = c;
+ }
+ c = NULL;
+ if (dset->findAndGetString(DCM_DeviceSerialNumber, c).good() && c)
+ {
+ deviceSerialNumber_ = c;
+ }
+ c = NULL;
+ if (dset->findAndGetString(DCM_SoftwareVersions, c).good() && c)
+ {
+ softwareVersions_ = c;
}
- if (ftype == "stl")
+
+ if (ftype_ == DT_stlDocument || ftype_ == DT_mtlDocument || ftype_ == DT_objDocument)
{
- OFLOG_TRACE(appLogger, "reading STL specific information");
+ DCMDATA_TRACE("reading STL/MTL/OBJ specific information");
c = NULL;
- OFLOG_TRACE(appLogger, "reading Frame of Reference Info");
if (dset->findAndGetString(DCM_FrameOfReferenceUID, c).good() && c)
{
- opt_frameOfReferenceUID = c;
+ frameOfReferenceUID_ = c;
}
c = NULL;
if (dset->findAndGetString(DCM_PositionReferenceIndicator, c).good() && c)
{
- opt_positionReferenceIndicator = c;
- }
- OFLOG_TRACE(appLogger, "reading Enhanced Equipment info");
- c = NULL;
- if (dset->findAndGetString(DCM_Manufacturer, c).good() && c)
- {
- opt_manufacturer = c;
- }
- c = NULL;
- if (dset->findAndGetString(DCM_ManufacturerModelName, c).good() && c)
- {
- opt_manufacturerModelName = c;
- }
- c = NULL;
- if (dset->findAndGetString(DCM_DeviceSerialNumber, c).good() && c)
- {
- opt_deviceSerialNumber = c;
+ positionReferenceIndicator_ = c;
}
- c = NULL;
- if (dset->findAndGetString(DCM_SoftwareVersions, c).good() && c)
- {
- opt_softwareVersions = c;
- }
- OFLOG_TRACE(appLogger, "reading manufacturing 3d model info");
- {
- OFLOG_TRACE(appLogger, "manufacturing 3d model info read successfully");
- }
}
}
}
+ else
+ {
+ DCMDATA_ERROR("Error reading series file '" << seriesFile_ << "': " << cond.text());
+ return cond;
+ }
}
- if (opt_studyUID.empty())
+
+ if (studyUID_.empty())
{
dcmGenerateUniqueIdentifier(buf, SITE_STUDY_UID_ROOT);
- opt_studyUID = buf;
+ studyUID_ = buf;
}
- if (opt_seriesUID.empty())
+ if (seriesUID_.empty())
{
dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT);
- opt_seriesUID = buf;
+ seriesUID_ = buf;
}
+
return cond;
}
-int DcmEncapsulatedDocument::insertEncapsulatedDocument(
- DcmItem *dataset,
- OFLogger &appLogger)
+
+OFCondition DcmEncapsulatedDocument::formatSpecificProcessing()
{
- char buf[100];
- size_t fileSize = 0;
- size_t buflen = 100;
- struct stat fileStat;
+ if (ftype_ == DT_cdaDocument)
+ {
+ // so far we only have format specific processing code for CDA
+ return getCDAData();
+ }
+ return EC_Normal;
+}
- if (0 == stat(opt_ifname.c_str(), &fileStat))
- {
- fileSize = OFstatic_cast(size_t, fileStat.st_size);
- }
- else
- {
- OFLOG_ERROR(appLogger, "file " << opt_ifname << " not found");
- return EXITCODE_NO_INPUT_FILES;
- }
- if (fileSize == 0)
- {
- OFLOG_ERROR(appLogger, "file " << opt_ifname << " is empty");
- return EXITCODE_INVALID_INPUT_FILE;
- }
- FILE *encapfile = fopen(opt_ifname.c_str(), "rb");
- if (encapfile == NULL)
- {
- OFLOG_ERROR(appLogger, "unable to read file " << opt_ifname);
- return EXITCODE_CANNOT_READ_INPUT_FILE;
- }
- if (fileSize < buflen)
- {
- buflen = fileSize;
- }
- if (buflen != fread(buf, 1, buflen, encapfile))
- {
- OFLOG_ERROR(appLogger, "read error in file " << opt_ifname);
- fclose(encapfile);
- return EXITCODE_INVALID_INPUT_FILE;
- }
- if (ftype == "pdf")
- {
- // check magic word for PDF file
- if (0 != strncmp("%PDF-", buf, 5))
+static size_t skipWhitespaceAndCommentLines(const char *buf, size_t buflen)
+{
+ size_t i=0;
+ while (OFTrue)
{
- OFLOG_ERROR(appLogger, "file " << opt_ifname << " is not a PDF file");
- fclose(encapfile);
- return EXITCODE_INVALID_INPUT_FILE;
+ // skip whitespace at beginning of line
+ while (i < buflen && (buf[i]==' ' || buf[i]=='\t')) ++i;
+
+ // skip comment line
+ if ((i < buflen) && (buf[i] == '#'))
+ {
+ // skip to the end of the comment line
+ while (i < buflen && (buf[i] != '\r' && buf[i] != '\n')) ++i;
+ }
+ else if (i < buflen && (buf[i]=='\r' || buf[i]=='\n'))
+ {
+ // skip empty line
+ ++i;
+ }
+ else return i; // end of buffer or keyword found
}
- // check PDF version number
- char *version = buf + 5;
- OFBool found = OFFalse;
- for (int i = 0; i < 5; ++i)
+}
+
+static OFString getNextKeyword(const char *buf)
+{
+ size_t i=0;
+ char c = buf[i];
+ while ((c != ' ') && (c != '\t') && (c != '\0') && (c != '\r') && (c != '\n'))
{
- if (version[i] == 10 || version[i] == 13)
- {
- version[i] = 0; // insert end of string
- found = OFTrue;
- break;
- }
+ ++i;
+ c = buf[i];
+ }
+ return OFString(buf, i);
+}
+
+static const char *objKeywords[] = {
+ "bevel", "bmat", "c_interp", "con", "cstype", "ctech", "curv", "curv2",
+ "d_interp", "deg", "end", "f", "g", "hole", "l", "lod", "mg", "mtllib",
+ "o", "p", "parm", "s", "scrv", "shadow_obj", "sp", "stech", "step",
+ "surf", "trace_obj", "trim", "usemtl", "v", "vn", "vp", "vt"
+};
+
+
+OFCondition DcmEncapsulatedDocument::insertEncapsulatedDocument()
+{
+#define INSERTBUFFERLENGTH 4096
+ char buf[INSERTBUFFERLENGTH+1];
+ size_t fileSize = 0;
+ size_t buflen = INSERTBUFFERLENGTH;
+ struct stat fileStat;
+ DcmDataset *dataset = dfile_.getDataset();
+
+ // determine length of document file
+ if (0 == stat(ifname_.c_str(), &fileStat))
+ {
+ fileSize = OFstatic_cast(size_t, fileStat.st_size);
+ }
+ else
+ {
+ DCMDATA_ERROR("file " << ifname_ << " not found");
+ return EC_InvalidStream;
+ }
+ if (fileSize == 0)
+ {
+ DCMDATA_ERROR("file " << ifname_ << " is empty");
+ return EC_InvalidStream;
+ }
+
+ // read the first 4096 bytes (or the full document if shorter)
+ FILE *encapfile = fopen(ifname_.c_str(), "rb");
+ if (encapfile == NULL)
+ {
+ DCMDATA_ERROR("unable to read file " << ifname_);
+ return EC_InvalidStream;
}
- if (!found)
+ if (fileSize < buflen)
{
- OFLOG_ERROR(appLogger, "file " << opt_ifname
- << ": unable to decode PDF version number");
+ buflen = fileSize;
+ }
+ if (buflen != fread(buf, 1, buflen, encapfile))
+ {
+ DCMDATA_ERROR("read error in file " << ifname_);
fclose(encapfile);
- return EXITCODE_INVALID_INPUT_FILE;
+ return EC_InvalidStream;
}
- OFLOG_INFO(appLogger, "file " << opt_ifname
- << ": PDF " << version << ", "
- << (fileSize + 1023) / 1024 << "kB");
- }
- else
- {
- if (ftype == "cda")
+
+ // null terminate buffer
+ buf[buflen] = '\0';
+
+ // if the user has not specified the file type, determine it from the file content
+
+ // check for PDF document type
+ if (ftype_ == DT_unknownDocument)
{
- //xml validation occurs when getting data
- OFLOG_INFO(appLogger, "file " << opt_ifname
- << ": HL7 CDA file (XML Format)" << ", "
- << (fileSize + 1023) / 1024 << "kB");
+ // If the document starts with "%PDF-", it is a PDF document
+ if ((buflen > 5) && (0 == strncmp("%PDF-", buf, 5))) ftype_ = DT_pdfDocument;
}
- else
+
+ // check for CDA document type
+ if (ftype_ == DT_unknownDocument)
{
- if (ftype == "stl")
- {
- // Each facet contains:
- // - Normals: 3 floats (4 bytes)
- // - Vertices: 3x floats (4 byte each, 12 bytes total)
- // - AttributeCount: 1 short (2 bytes)
- // Total: 50 bytes per facet
- const size_t facetSize32 = 3 * sizeof(Float32)
- + 3 * 3 * sizeof(Float32)
- + sizeof(Uint16);
- const size_t facetSize64 = 3 * sizeof(Float64)
- + 3 * 3 * sizeof(Float64)
- + sizeof(Uint16);
- // STL validation for ASCII CODE
- if (fileSize < 15)
+ size_t i = 0;
+ // in a CDA document, the first non-whitespace character is "<"
+ while (i < buflen && OFStandard::isspace(buf[i])) ++i;
+ // we also check for the presence of the keyword "ClinicalDocument"
+ if ((i < buflen && buf[i] == '<') && (NULL != strstr(buf, "ClinicalDocument"))) ftype_ = DT_cdaDocument;
+ }
+
+ // check for binary STL document type
+ if (ftype_ == DT_unknownDocument)
+ {
+ // See comments in the STL section below for explanation of the identification algorithm
+ if (fileSize >= 84)
{
- // "solid " and "endsolid " markers for an ASCII file
- OFLOG_ERROR(appLogger, "The STL file is not long enough"
- << " (" << fileSize << "kB)");
- fclose(encapfile);
- return EXITCODE_INVALID_INPUT_FILE;
+ const size_t facetSize32 = 12 * sizeof(Float32) + sizeof(Uint16);
+ const size_t facetSize64 = 12 * sizeof(Float64) + sizeof(Uint16);
+
+ // the number of triangles is stored as a 32-bit little endian integer at byte offset 80 in the file
+ Uint32 nTriangles = 0;
+ for (int j = 3; j >= 0; --j)
+ {
+ nTriangles = (nTriangles << 8) + OFstatic_cast(unsigned char, buf[80 + j]);
+ }
+ if (fileSize == (84 + nTriangles * facetSize32) || fileSize == (84 + nTriangles * facetSize64)) ftype_ = DT_stlDocument;
}
- // Binary files should never start with "solid ",
- // but just in case, check for ASCII,
- // and if not valid then check for binary...
- // Look for text "solid " in first 6 bytes,
- // indicating the possibility that this is an
- // ASCII STL format.
- if (0 == strncmp("solid ", buf, 6))
+ }
+
+ // check for MTL document type
+ if (ftype_ == DT_unknownDocument)
+ {
+ size_t i = skipWhitespaceAndCommentLines(buf, buflen);
+ if (i < buflen)
{
- OFLOG_ERROR(appLogger, "File " << opt_ifname
- << " starts with 'solid '. "
- << "It is a valid STL file but it is in ASCII Code"
- << "and DICOM only accepts binary STL");
- return EXITCODE_INVALID_INPUT_FILE;
+ OFString keyword = getNextKeyword(buf+i);
+ if (keyword == "newmtl") ftype_ = DT_mtlDocument;
}
- //////STL validation for Binary Format
- else
+ }
+
+ // check for OBJ document type
+ if (ftype_ == DT_unknownDocument)
+ {
+ size_t i = skipWhitespaceAndCommentLines(buf, buflen);
+ if (i < buflen)
{
- OFLOG_DEBUG(appLogger, "Magic word 'solid ' not found. "
- << "Validating STL file "
- << "in Binary format");
- // 80-byte header + 4-byte "number of triangles" for a binary file
- if (fileSize < 84)
+ OFString keyword = getNextKeyword(buf+i);
+ size_t numKeywords = sizeof(objKeywords)/sizeof(const char *);
+ for (size_t j=0; j < numKeywords; ++j)
{
- OFLOG_ERROR(appLogger, "The binary STL file is not long enough"
- << " (" << fileSize << "kB)");
- fclose(encapfile);
- return EXITCODE_INVALID_INPUT_FILE;
+ if (keyword == objKeywords[j])
+ {
+ ftype_ = DT_objDocument;
+ break;
+ }
}
- // Header is from bytes 0-79
- // The number of Triangles starts at byte offset 80 and is a uint32 (4 Bytes)
- char ntriangleschar[5];
- for (int j = 0; j < 4; j++)
- ntriangleschar[j] = buf[80 + j];
- ntriangleschar[4] = 0;
- Uint32 *nTriangles = OFreinterpret_cast(Uint32*, ntriangleschar);
- // Verify that file size equals the sum of
- // header + nTriangles value + all triangles
- OFLOG_DEBUG(appLogger, "verifying if the file size is consistent");
- if (fileSize == (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize32) ||
- fileSize == (84 + *OFconst_cast(Uint32*, nTriangles) * facetSize64))
- {
- OFLOG_DEBUG(appLogger, "File " << opt_ifname
- << " passed binary STL validation." << OFendl
- << "Assuming valid STL file "
- << "in binary format"
- );
- OFLOG_TRACE(appLogger, "The binary STL file is:" << OFendl
- << fileSize << " kB " << " as expected." << OFendl
- << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize32) << " kB for x86" << OFendl
- << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize64) << " kB for x64" << OFendl
- << "(84 + triangles number * facet size)" << OFendl
- << " number of Triangles " << *OFconst_cast(Uint32 * , nTriangles) << OFendl
- << " nTriangles (Uint32): " << nTriangles << OFendl
- << " facetSize32: " << facetSize32 << OFendl
- << " facetSize64: " << facetSize64 << OFendl
- );
- }
- else
- {
- OFLOG_ERROR(appLogger, "The binary STL file is not consistent." << OFendl
- << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize32) << " kB for x86 and "
- << (84 + *OFconst_cast(Uint32 * , nTriangles) * facetSize64) << " kB for x64 " << OFendl
- << "(84 + triangles number * facet size)" << OFendl
- << " number of Triangles " << *OFconst_cast(Uint32 * , nTriangles) << OFendl
- << " nTriangles (Uint32): " << nTriangles << OFendl
- << " facetSize32: " << facetSize32 << OFendl
- << " facetSize64: " << facetSize64 << OFendl
- );
+ }
+ }
+
+ // check if we have determined the file type, bail out otherwise
+ if (ftype_ == DT_unknownDocument)
+ {
+ DCMDATA_ERROR("file " << ifname_ << " is of unknown file type");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+
+ OFBool found;
+ char *version;
+
+ // Each STL facet contains:
+ // - Normals: 3 floats (4 bytes)
+ // - Vertices: 3x floats (4 byte each, 12 bytes total)
+ // - AttributeCount: 1 short (2 bytes)
+ // Total: 50 bytes per facet
+ const size_t facetSize32 = 12 * sizeof(Float32) + sizeof(Uint16);
+ const size_t facetSize64 = 12 * sizeof(Float64) + sizeof(Uint16);
+ size_t i;
+
+ switch (ftype_)
+ {
+ case DT_pdfDocument: // special handling for PDF documents
+ // check magic word for PDF file
+ if (0 != strncmp("%PDF-", buf, 5))
+ {
+ DCMDATA_ERROR("file " << ifname_ << " is not a PDF file");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ // check PDF version number
+ version = buf + 5;
+ found = OFFalse;
+ for (i = 0; i < 5; ++i)
+ {
+ if (version[i] == 10 || version[i] == 13)
+ {
+ version[i] = 0; // insert end of string
+ found = OFTrue;
+ break;
+ }
+ }
+ if (!found)
+ {
+ DCMDATA_ERROR("file " << ifname_ << ": unable to decode PDF version number");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ DCMDATA_INFO("file " << ifname_ << ": PDF " << version << ", " << (fileSize + 1023) / 1024 << "kB");
+ break;
+
+ case DT_cdaDocument: // special handling for CDA documents
+ // proper xml validation occurs later
+ DCMDATA_INFO("file " << ifname_ << ": HL7 CDA file (XML Format)" << ", " << (fileSize + 1023) / 1024 << "kB");
+ break;
+
+ case DT_stlDocument: // special handling for STL documents
+ // Check for an ASCII STL document (which is not permitted in DICOM)
+ if (fileSize < 15)
+ {
+ // "solid " and "endsolid " markers for an ASCII file
+ DCMDATA_ERROR("The STL file is not long enough" << " (" << fileSize << "kB)");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+
+ // Binary STL files should never start with "solid ", but just in case, check for ASCII,
+ // and if not valid then check for binary... Look for text "solid " in first 6 bytes,
+ // indicating the possibility that this is an ASCII STL format.
+ if (0 == strncmp("solid ", buf, 6))
+ {
+ DCMDATA_ERROR("File " << ifname_ << " starts with 'solid '. It is an STL file but it is in ASCII and DICOM only permits binary STL");
+ return EC_InvalidStream;
+ }
+ else
+ {
+ // STL validation for Binary Format
+ DCMDATA_DEBUG("Validating binary STL file");
+ // 80-byte header + 4-byte "number of triangles" for a binary file
+ if (fileSize < 84)
+ {
+ DCMDATA_ERROR("The binary STL file is not long enough" << " (" << fileSize << "kB)");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ // Header is from bytes 0-79
+ // The number of Triangles starts at byte offset 80 and is a
+ // unsigned 32-bit integer in little endian byte order
+ Uint32 nTriangles = 0;
+ for (int j = 3; j >= 0; --j)
+ nTriangles = (nTriangles << 8) + OFstatic_cast(unsigned char, buf[80 + j]);
+
+ // Verify that file size equals the sum of
+ // header + nTriangles value + all triangles
+ DCMDATA_DEBUG("verifying if the file size is consistent");
+ if (fileSize == (84 + nTriangles * facetSize32) ||
+ fileSize == (84 + nTriangles * facetSize64))
+ {
+ DCMDATA_INFO("file " << ifname_ << ": binary STL, " << nTriangles << " triangles");
+ DCMDATA_DEBUG("The binary STL file is "
+ << fileSize << " bytes (expected "
+ << (84 + nTriangles * facetSize32) << " bytes for x86 or "
+ << (84 + nTriangles * facetSize64) << " bytes for x64), number of triangles: " << nTriangles);
+ }
+ else
+ {
+ DCMDATA_ERROR("The binary STL file is not consistent. Expected "
+ << (84 + nTriangles * facetSize32) << " bytes for x86 or "
+ << (84 + nTriangles * facetSize64) << " bytes for x64");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ }
+ break;
+
+ case DT_mtlDocument: // special handling for MTL documents
+ i = skipWhitespaceAndCommentLines(buf, buflen);
+ if (i < buflen)
+ {
+ OFString keyword = getNextKeyword(buf+i);
+ if (keyword != "newmtl")
+ {
+ DCMDATA_ERROR("Not a valid MTL file. Expected 'newmtl' as first keyword, but found '" << keyword << "'");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ }
+ else
+ {
+ DCMDATA_ERROR("Not a valid MTL file. No keyword found");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ DCMDATA_INFO("file " << ifname_ << ": Wavefront MTL");
+ break;
+
+ case DT_objDocument: // special handling for OBJ documents
+ i = skipWhitespaceAndCommentLines(buf, buflen);
+ if (i < buflen)
+ {
+ OFString keyword = getNextKeyword(buf+i);
+ size_t numKeywords = sizeof(objKeywords)/sizeof(const char *);
+ found = OFFalse;
+ for (size_t j=0; j < numKeywords; ++j)
+ {
+ if (keyword == objKeywords[j])
+ {
+ found = OFTrue;
+ break;
+ }
+ }
+ if (!found)
+ {
+ DCMDATA_ERROR("Not a valid OBJ file. Unsupported keyword '" << keyword << "' found");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ }
+ else
+ {
+ DCMDATA_ERROR("Not a valid OBJ file. No keyword found");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+ DCMDATA_INFO("file " << ifname_ << ": Wavefront OBJ");
+ break;
+
+ case DT_unknownDocument:
+ DCMDATA_ERROR("Unsupported filetype. This should not happen.");
fclose(encapfile);
- return EXITCODE_INVALID_INPUT_FILE;
- }
+ return EC_InvalidStream;
+ break;
+ }
+
+ // seek to start of file
+ if (0 != fseek(encapfile, 0, SEEK_SET))
+ {
+ DCMDATA_ERROR("file " << ifname_ << ": seek error");
+ fclose(encapfile);
+ return EC_InvalidStream;
+ }
+
+ OFCondition result = EC_Normal;
+ DcmPolymorphOBOW *elem = new DcmPolymorphOBOW(DCM_EncapsulatedDocument);
+ if (elem)
+ {
+ size_t numBytes = fileSize;
+
+ // Store Encapsulated Document Length, according to CP 1851
+ result = dataset->putAndInsertUint32(DCM_EncapsulatedDocumentLength, OFstatic_cast(Uint32, numBytes));
+
+ // allocate an even number of bytes
+ if (numBytes & 1) ++numBytes;
+ Uint8 *bytes = NULL;
+ if (result.good())
+ {
+ result = elem->createUint8Array(OFstatic_cast(Uint32, numBytes), bytes);
+ }
+ else
+ {
+ return result;
+ }
+
+ // read file content into Encapsulated Document attribute
+ if (result.good())
+ {
+ // blank pad byte
+ bytes[numBytes - 1] = 0;
+ // read file content
+ if (fileSize != fread(bytes, 1, fileSize, encapfile))
+ {
+ DCMDATA_ERROR("read error in file " << ifname_);
+ return result;
}
}
else
{
- OFLOG_WARN(appLogger, "Filetype not supported or filetype not set. Current ftype is " << ftype << OFendl
- << "The name of the passed logger is: " << appLogger.getName());
+ return EC_MemoryExhausted;
}
}
- }
- if (0 != fseek(encapfile, 0, SEEK_SET))
- {
- OFLOG_ERROR(appLogger, "file " << opt_ifname << ": seek error");
- fclose(encapfile);
- return EXITCODE_CANNOT_READ_INPUT_FILE;
- }
- OFCondition result = EC_Normal;
- DcmPolymorphOBOW *elem = new DcmPolymorphOBOW(DCM_EncapsulatedDocument);
- if (elem)
- {
- size_t numBytes = fileSize;
- // according to CP 1851
- result = dataset->putAndInsertUint32(DCM_EncapsulatedDocumentLength, OFstatic_cast(Uint32, numBytes));
- if (numBytes & 1) ++numBytes;
- Uint8 *bytes = NULL;
- if (result.good())
- {
- result = elem->createUint8Array(OFstatic_cast(Uint32, numBytes), bytes);
- }
else
{
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
+ fclose(encapfile);
+ return EC_MemoryExhausted;
}
+ // if successful, insert Encapsulated Document element into dataset
if (result.good())
{
- // blank pad byte
- bytes[numBytes - 1] = 0;
- // read file content
- if (fileSize != fread(bytes, 1, fileSize, encapfile))
- {
- OFLOG_ERROR(appLogger, "read error in file " << opt_ifname);
- return EXITCODE_CANNOT_READ_INPUT_FILE;
- }
+ result = dataset->insert(elem);
}
else
{
- return EXITCODE_MEMORY_EXHAUSTED;
+ delete elem;
+ DCMDATA_ERROR("Unsuccessful, did not insert element.");
+ return result;
}
- }
- else
- {
+
+ // close file end return
fclose(encapfile);
- return EXITCODE_MEMORY_EXHAUSTED;
- }
- // if successful, insert element into dataset
- if (result.good())
- {
- result = dataset->insert(elem);
- }
- else
- {
- delete elem;
- OFLOG_ERROR(appLogger, "Unsuccessful, did not insert element.");
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
- // close file
- fclose(encapfile);
- if (result.good())
- {
- return EXITCODE_NO_ERROR;
- }
- else
- {
- return EXITCODE_CANNOT_WRITE_OUTPUT_FILE;
- }
+ return result;
}
-OFCondition DcmEncapsulatedDocument::createHeader(
- DcmItem *dataset,
- OFLogger &logger)
+OFCondition DcmEncapsulatedDocument::addFrameOfReferenceModule(DcmItem *dataset)
{
- OFCondition result = EC_Normal;
- char buf[80];
- // insert empty type 2 attributes
- if (result.good()) result = dataset->insertEmptyElement(DCM_StudyDate);
- if (result.good()) result = dataset->insertEmptyElement(DCM_StudyTime);
- if (result.good()) result = dataset->insertEmptyElement(DCM_AccessionNumber);
- if (result.good()) result = dataset->insertEmptyElement(DCM_Manufacturer);
- if (result.good()) result = dataset->insertEmptyElement(DCM_ReferringPhysicianName);
- if (result.good()) result = dataset->insertEmptyElement(DCM_StudyID);
- if (result.good()) result = dataset->insertEmptyElement(DCM_ContentDate);
- if (result.good()) result = dataset->insertEmptyElement(DCM_ContentTime);
- if (result.good()) result = dataset->insertEmptyElement(DCM_AcquisitionDateTime);
- if (result.good())
- {
- if (opt_conceptCSD != "" && opt_conceptCV != "" && opt_conceptCM != "")
+ DCMDATA_TRACE("Validating Frame of Reference UID value");
+ char buf [100];
+ if (frameOfReferenceUID_.empty())
{
- result = DcmCodec::insertCodeSequence(dataset, DCM_ConceptNameCodeSequence,
- opt_conceptCSD.c_str(),
- opt_conceptCV.c_str(),
- opt_conceptCM.c_str());
+ DCMDATA_DEBUG("Frame of Reference UID " << DCM_FrameOfReferenceUID << " value missing, generating a new one."
+ );
+ dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT);
+ frameOfReferenceUID_ = buf;
}
else
{
- result = dataset->insertEmptyElement(DCM_ConceptNameCodeSequence);
+ if (DcmUniqueIdentifier::checkStringValue(frameOfReferenceUID_, "1").bad())
+ {
+ DCMDATA_DEBUG("Frame of Reference UID " << DCM_FrameOfReferenceUID << " value was faulty, generating a new one."
+ );
+ dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT);
+ frameOfReferenceUID_ = buf;
+ }
}
- }
- // insert const value attributes
- if (result.good())
- {
- result = dataset->putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 100");
- }
- //insert encapsulated file storage UID (CDA/PDF/STL)
- if (result.good())
- {
- if (ftype == "pdf")
+ DCMDATA_TRACE("Inserting Frame of Reference info to dataset");
+ OFCondition result = dataset->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, frameOfReferenceUID_);
+
+ if (result.good())
+ result = dataset->putAndInsertOFStringArray(DCM_PositionReferenceIndicator, positionReferenceIndicator_);
+
+ return result;
+}
+
+
+OFCondition DcmEncapsulatedDocument::addEnhancedGeneralEquipmentModule(DcmItem *dataset)
+{
+ DCMDATA_TRACE("Validating and inserting Enhanced General Equipment fields");
+ if (manufacturer_.empty())
{
- OFLOG_TRACE(logger, "Inserting SOPClassUID to dataset");
- result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedPDFStorage);
+ manufacturer_ = "DCMTK_MANUFACTURING";
+ DCMDATA_INFO("No Manufacturer " << DCM_Manufacturer << " specified, will use dummy value.");
}
- if (ftype == "cda")
+ OFCondition result = dataset->putAndInsertOFStringArray(DCM_Manufacturer, manufacturer_);
+ if (result.good())
{
- OFLOG_TRACE(logger, "Inserting SOPClassUID to dataset");
- result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedCDAStorage);
- }
- if (ftype == "stl")
- {//STL Specific modules
- OFLOG_TRACE(logger, "Validating Frame of Reference UID value");
- if (opt_frameOfReferenceUID.empty())
- {
- OFLOG_DEBUG(logger, "Frame of Reference UID "
- << DCM_FrameOfReferenceUID
- << " value was empty, generating a new one."
- );
- dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT);
- opt_frameOfReferenceUID = buf;
- }
- else
- {
- if (DcmUniqueIdentifier::checkStringValue(opt_frameOfReferenceUID, "1").bad())
- {
- OFLOG_DEBUG(logger, "Frame of Reference UID "
- << DCM_FrameOfReferenceUID
- << " value was faulty, generating a new one."
- );
- dcmGenerateUniqueIdentifier(buf, SITE_SERIES_UID_ROOT);
- opt_frameOfReferenceUID = buf;
- }
- }
- if (result.good())
- {
- OFLOG_TRACE(logger, "Inserting Frame of Reference info to dataset");
- result = dataset->putAndInsertOFStringArray(DCM_FrameOfReferenceUID, opt_frameOfReferenceUID);
- }
- if (result.good())
- result = dataset->putAndInsertOFStringArray(DCM_PositionReferenceIndicator, opt_positionReferenceIndicator);
- OFLOG_TRACE(logger, "Validating and inserting Enhanced General Equipment fields");
- if (result.good())
- {
- if (opt_manufacturer.empty())
+ if (manufacturerModelName_.empty())
{
- opt_manufacturer = "DCMTK_MANUFACTURING";
- OFLOG_WARN(logger, "No Manufacturer "
- << DCM_Manufacturer
- << " provided nor found in series. This attribute is "
- << "required for Enhanced General Equipment module. "
- << opt_manufacturer
- << " will be inserted as dummy value."
- );
+ manufacturerModelName_ = "DCMTK_3DMODEL";
+ DCMDATA_INFO("No Manufacturer Model Name " << DCM_ManufacturerModelName << " specified, will use dummy value.");
}
- result = dataset->putAndInsertOFStringArray(DCM_Manufacturer, opt_manufacturer);
- }
- if (result.good())
- {
- if (opt_manufacturerModelName.empty())
- {
- opt_manufacturerModelName = "DCMTK_3DMODEL_3";
- OFLOG_WARN(logger, "No Manufacturer Model Name "
- << DCM_ManufacturerModelName
- << " provided nor found in series. This attribute is "
- << "required for Enhanced General Equipment module. "
- << opt_manufacturerModelName
- << " will be inserted as dummy value."
- );
- }
- result = dataset->putAndInsertOFStringArray(DCM_ManufacturerModelName, opt_manufacturerModelName);
- }
- if (result.good())
- {
- if (opt_deviceSerialNumber.empty())
- {
- opt_deviceSerialNumber = "DCMTK01234567890";
- OFLOG_WARN(logger, "No Device Serial Number "
- << DCM_DeviceSerialNumber
- << " provided nor found in series. This attribute is "
- << "required for Enhanced General Equipment module. "
- << opt_deviceSerialNumber
- << " will be inserted as dummy value."
- );
- }
- result = dataset->putAndInsertOFStringArray(DCM_DeviceSerialNumber, opt_deviceSerialNumber);
- }
- if (result.good())
- {
- if (opt_softwareVersions.empty())
- {
- opt_softwareVersions = OFFIS_DCMTK_VERSION;
- OFLOG_WARN(logger, "No Software Versions "
- << DCM_SoftwareVersions
- << " provided nor found in series. This attribute is "
- << "required for Enhanced General Equipment module. "
- << opt_softwareVersions
- << " will be inserted as dummy value."
- );
- }
- result = dataset->putAndInsertOFStringArray(DCM_SoftwareVersions, opt_softwareVersions);
- }
- if (result.good())
- {
- if (opt_measurementUnitsCSD != "" && opt_measurementUnitsCV != "" && opt_measurementUnitsCM != "")
+ result = dataset->putAndInsertOFStringArray(DCM_ManufacturerModelName, manufacturerModelName_);
+ }
+ if (result.good())
+ {
+ if (deviceSerialNumber_.empty())
{
- result = DcmCodec::insertCodeSequence(dataset, DCM_MeasurementUnitsCodeSequence,
- opt_measurementUnitsCSD.c_str(),
- opt_measurementUnitsCV.c_str(),
- opt_measurementUnitsCM.c_str());
+ deviceSerialNumber_ = "DCMTK_1234567890";
+ DCMDATA_INFO("No Device Serial Number " << DCM_DeviceSerialNumber << " specified, will use dummy value.");
}
- else
+ result = dataset->putAndInsertOFStringArray(DCM_DeviceSerialNumber, deviceSerialNumber_);
+ }
+ if (result.good())
+ {
+ if (softwareVersions_.empty())
{
- OFLOG_DEBUG(logger, "Measurement Units Code Sequence "
- << DCM_FrameOfReferenceUID
- << "had one or more empty values, generating default values."
- );
- result = DcmCodec::insertCodeSequence(dataset, DCM_MeasurementUnitsCodeSequence, "UCUM", "um", "um");
+ softwareVersions_ = OFFIS_DCMTK_VERSION;
+ DCMDATA_INFO("No Software Versions " << DCM_SoftwareVersions << " specified, will use dummy value.");
}
- }
- if (result.good())
- {
- OFLOG_TRACE(logger, "Inserting SOPClassUID to dataset");
- result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedSTLStorage);
- }
+ result = dataset->putAndInsertOFStringArray(DCM_SoftwareVersions, softwareVersions_);
}
- }
- if (result.good())
- {
- if (ftype == "stl")
+ return result;
+}
+
+
+OFCondition DcmEncapsulatedDocument::addManufacturing3DModelModule(DcmItem *dataset)
+{
+ OFCondition result = EC_Normal;
+
+ if ((measurementUnitsCSD_.length() > 0) && (measurementUnitsCV_.length() > 0) && (measurementUnitsCM_.length() > 0))
{
- result = dataset->putAndInsertString(DCM_Modality, "M3D");
+ result = DcmCodec::insertCodeSequence(dataset, DCM_MeasurementUnitsCodeSequence,
+ measurementUnitsCSD_.c_str(),
+ measurementUnitsCV_.c_str(),
+ measurementUnitsCM_.c_str());
}
else
{
- // we are now using "DOC" for the modality, which seems to be more appropriate than "OT" (see CP-749)
- result = dataset->putAndInsertString(DCM_Modality, "DOC");
+ DCMDATA_DEBUG("Measurement Units Code Sequence "
+ << DCM_MeasurementUnitsCodeSequence
+ << " had one or more empty values, generating default values."
+ );
+ result = DcmCodec::insertCodeSequence(dataset, DCM_MeasurementUnitsCodeSequence, "UCUM", "um", "um");
}
- }
- if (result.good())
- {
- if (ftype != "stl")
+ return result;
+}
+
+
+OFCondition DcmEncapsulatedDocument::createHeader()
+{
+ OFCondition result = EC_Normal;
+ DcmDataset *dataset = dfile_.getDataset();
+
+ char buf[80];
+ // insert empty type 2 attributes
+ if (result.good()) result = dataset->insertEmptyElement(DCM_StudyDate);
+ if (result.good()) result = dataset->insertEmptyElement(DCM_StudyTime);
+ if (result.good()) result = dataset->insertEmptyElement(DCM_AccessionNumber);
+ if (result.good()) result = dataset->insertEmptyElement(DCM_ReferringPhysicianName);
+ if (result.good()) result = dataset->insertEmptyElement(DCM_StudyID);
+ if (result.good()) result = dataset->insertEmptyElement(DCM_ContentDate);
+ if (result.good()) result = dataset->insertEmptyElement(DCM_ContentTime);
+ if (result.good()) result = dataset->insertEmptyElement(DCM_AcquisitionDateTime);
+ if (result.good())
{
- OFLOG_TRACE(logger, "Inserting default Conversion type: Workstation (WSD) to dataset");
- result = dataset->putAndInsertString(DCM_ConversionType, "WSD");
+ if ((conceptCSD_.length() > 0) && (conceptCV_.length() > 0) && (conceptCM_.length() > 0))
+ {
+ result = DcmCodec::insertCodeSequence(dataset, DCM_ConceptNameCodeSequence,
+ conceptCSD_.c_str(),
+ conceptCV_.c_str(),
+ conceptCM_.c_str());
+ }
+ else
+ {
+ result = dataset->insertEmptyElement(DCM_ConceptNameCodeSequence);
+ }
}
- else
+
+ // there is no way we could determine a meaningful series number, so we just use a constant.
+ if (result.good()) result = dataset->putAndInsertString(DCM_SeriesNumber, "1");
+
+ // insert variable value attributes
+ if (result.good()) result = dataset->putAndInsertString(DCM_DocumentTitle, documentTitle_.c_str());
+ if (result.good()) result = dataset->putAndInsertString(DCM_PatientName, patientName_.c_str());
+ if (result.good()) result = dataset->putAndInsertString(DCM_PatientID, patientID_.c_str());
+ if (result.good()) result = dataset->putAndInsertString(DCM_PatientBirthDate, patientBirthdate_.c_str());
+ if (result.good()) result = dataset->putAndInsertString(DCM_PatientSex, patientSex_.c_str());
+ if (result.good()) result = dataset->putAndInsertString(DCM_BurnedInAnnotation, annotation_ ? "YES" : "NO");
+ OFStandard::snprintf(buf, sizeof(buf), "%ld", OFstatic_cast(long, instance_));
+ if (result.good()) result = dataset->putAndInsertString(DCM_InstanceNumber, buf);
+ dcmGenerateUniqueIdentifier(buf, SITE_INSTANCE_UID_ROOT);
+ if (result.good()) result = dataset->putAndInsertString(DCM_StudyInstanceUID, studyUID_.c_str());
+ if (result.good()) result = dataset->putAndInsertString(DCM_SeriesInstanceUID, seriesUID_.c_str());
+ if (result.good()) result = dataset->putAndInsertString(DCM_SOPInstanceUID, buf);
+ // set instance creation date and time
+ OFString s;
+ if (result.good()) result = DcmDate::getCurrentDate(s);
+ if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate, s);
+ if (result.good()) result = DcmTime::getCurrentTime(s);
+ if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime, s);
+
+ // Device data. Special handling of these attributes for STL/MTL/OBJ,
+ // where they are type 1, will be provided later in addEnhancedGeneralEquipmentModule()
+ if (result.good() && (manufacturer_.length() > 0))
+ result = dataset->putAndInsertOFStringArray(DCM_Manufacturer, manufacturer_.c_str());
+ else result = dataset->insertEmptyElement(DCM_Manufacturer);
+ if (result.good() && (manufacturerModelName_.length() > 0)) result = dataset->putAndInsertOFStringArray(DCM_ManufacturerModelName, manufacturerModelName_.c_str());
+ if (result.good() && (deviceSerialNumber_.length() > 0)) result = dataset->putAndInsertOFStringArray(DCM_DeviceSerialNumber, deviceSerialNumber_.c_str());
+ if (result.good() && (softwareVersions_.length() > 0)) result = dataset->putAndInsertOFStringArray(DCM_SoftwareVersions, softwareVersions_.c_str());
+
+ //insert encapsulated file storage UID and additional attributes required per SOP class
+ if (result.good())
{
- OFLOG_TRACE(logger, "STL has no Conversion Type");
- result = EC_Normal;
+ switch (ftype_)
+ {
+ case DT_pdfDocument:
+ DCMDATA_TRACE("Inserting SOPClassUID to dataset");
+ result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedPDFStorage);
+ if (result.good()) result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "application/pdf");
+ if (result.good())
+ {
+ if ((modality_.length() > 0) && (modality_ != "DOC"))
+ {
+ DCMDATA_ERROR("Cannot use series information from '" << seriesFile_ << "': modality mismatch, expected 'DOC', found '" << modality_ << "'");
+ result = EC_InvalidValue;
+ }
+ else result = dataset->putAndInsertString(DCM_Modality, "DOC");
+ }
+ if (result.good()) result = dataset->putAndInsertString(DCM_ConversionType, "WSD");
+ if (result.good() && (specificCharSet_.length() > 0)) result = dataset->putAndInsertString(DCM_SpecificCharacterSet, specificCharSet_.c_str());
+ break;
+
+ case DT_cdaDocument:
+ DCMDATA_TRACE("Inserting SOPClassUID to dataset");
+ result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedCDAStorage);
+ if (result.good()) result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "text/XML");
+ if (result.good())
+ {
+ if ((modality_.length() > 0) && (modality_ != "DOC"))
+ {
+ DCMDATA_ERROR("Cannot use series information from '" << seriesFile_ << "': modality mismatch, expected 'DOC', found '" << modality_ << "'");
+ result = EC_InvalidValue;
+ }
+ else result = dataset->putAndInsertString(DCM_Modality, "DOC");
+ }
+ if (result.good()) result = dataset->putAndInsertString(DCM_ConversionType, "WSD");
+ // Patient Name and Patient ID are guaranteed to be in UTF-8 (ISO_IR 192) in the CDA document
+ // and no other attributes from the series file are affected by character set issues
+ if ((! override_) || (specificCharSet_.length() == 0) ) specificCharSet_ = "ISO_IR 192";
+ if (result.good()) result = dataset->putAndInsertString(DCM_SpecificCharacterSet, specificCharSet_.c_str());
+ if (result.good() && cda_mediaTypes.length() > 0)
+ {
+ result = dataset->putAndInsertString(DCM_ListOfMIMETypes, cda_mediaTypes.c_str());
+ }
+ if (result.good() && hl7_InstanceIdentifier.length() > 0)
+ {
+ result = dataset->putAndInsertString(DCM_HL7InstanceIdentifier, hl7_InstanceIdentifier.c_str());
+ }
+ break;
+
+ case DT_stlDocument:
+ DCMDATA_TRACE("Inserting SOPClassUID to dataset");
+ result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedSTLStorage);
+ if (result.good()) result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "model/stl");
+ if (result.good())
+ {
+ if ((modality_.length() > 0) && (modality_ != "M3D"))
+ {
+ DCMDATA_ERROR("Cannot use series information from '" << seriesFile_ << "': modality mismatch, expected 'M3D', found '" << modality_ << "'");
+ result = EC_InvalidValue;
+ }
+ else result = dataset->putAndInsertString(DCM_Modality, "M3D");
+ }
+ if (result.good() && (specificCharSet_.length() > 0)) result = dataset->putAndInsertString(DCM_SpecificCharacterSet, specificCharSet_.c_str());
+ if (result.good()) result = addFrameOfReferenceModule(dataset);
+ if (result.good()) result = addEnhancedGeneralEquipmentModule(dataset);
+ if (result.good()) result = addManufacturing3DModelModule(dataset);
+ break;
+
+ case DT_mtlDocument:
+ DCMDATA_TRACE("Inserting SOPClassUID to dataset");
+ result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedMTLStorage);
+ if (result.good()) result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "model/mtl");
+ if (result.good())
+ {
+ if ((modality_.length() > 0) && (modality_ != "M3D"))
+ {
+ DCMDATA_ERROR("Cannot use series information from '" << seriesFile_ << "': modality mismatch, expected 'M3D', found '" << modality_ << "'");
+ result = EC_InvalidValue;
+ }
+ else result = dataset->putAndInsertString(DCM_Modality, "M3D");
+ }
+ if (result.good() && (specificCharSet_.length() > 0)) result = dataset->putAndInsertString(DCM_SpecificCharacterSet, specificCharSet_.c_str());
+ if (result.good()) result = addFrameOfReferenceModule(dataset);
+ if (result.good()) result = addEnhancedGeneralEquipmentModule(dataset);
+ if (result.good()) result = addManufacturing3DModelModule(dataset);
+ break;
+
+ case DT_objDocument:
+ DCMDATA_TRACE("Inserting SOPClassUID to dataset");
+ result = dataset->putAndInsertString(DCM_SOPClassUID, UID_EncapsulatedOBJStorage);
+ if (result.good()) result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "model/obj");
+ if (result.good())
+ {
+ if ((modality_.length() > 0) && (modality_ != "M3D"))
+ {
+ DCMDATA_ERROR("Cannot use series information from '" << seriesFile_ << "': modality mismatch, expected 'M3D', found '" << modality_ << "'");
+ result = EC_InvalidValue;
+ }
+ else result = dataset->putAndInsertString(DCM_Modality, "M3D");
+ }
+ if (result.good() && (specificCharSet_.length() > 0)) result = dataset->putAndInsertString(DCM_SpecificCharacterSet, specificCharSet_.c_str());
+ if (result.good()) result = addFrameOfReferenceModule(dataset);
+ if (result.good()) result = addEnhancedGeneralEquipmentModule(dataset);
+ if (result.good()) result = addManufacturing3DModelModule(dataset);
+ break;
+
+ case DT_unknownDocument:
+ break;
+ }
}
- }
- if (result.good())
- {
- // according to C.24.2.1 on part 3, (0042,0012) is text/XML for CDA.
- if (ftype == "cda")
- result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "text/XML");
- // according to A.45.1.4.1 on part 3, MIME Type is application/pdf for PDF.
- if (ftype == "pdf")
- result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "application/pdf");
- // according to A.85.1.4.2 on part 3, MIME Type is model/stl.
- if (ftype == "stl")
- result = dataset->putAndInsertString(DCM_MIMETypeOfEncapsulatedDocument, "model/stl");
- }
- // there is no way we could determine a meaningful series number, so we just use a constant.
- if (result.good()) result = dataset->putAndInsertString(DCM_SeriesNumber, "1");
- // insert variable value attributes
- if (result.good()) result = dataset->putAndInsertString(DCM_DocumentTitle, opt_documentTitle.c_str());
- if (result.good()) result = dataset->putAndInsertString(DCM_PatientName, opt_patientName.c_str());
- if (result.good()) result = dataset->putAndInsertString(DCM_PatientID, opt_patientID.c_str());
- if (result.good()) result = dataset->putAndInsertString(DCM_PatientBirthDate, opt_patientBirthdate.c_str());
- if (result.good()) result = dataset->putAndInsertString(DCM_PatientSex, opt_patientSex.c_str());
- if (result.good()) result = dataset->putAndInsertString(DCM_BurnedInAnnotation, opt_annotation ? "YES" : "NO");
- if (strlen(cda_mediaTypes.c_str()) > 0)
- {
- if (result.good()) result = dataset->putAndInsertString(DCM_ListOfMIMETypes, cda_mediaTypes.c_str());
- }
- if (hl7_InstanceIdentifier.size() > 0)
- {
- if (result.good()) result = dataset->putAndInsertString(DCM_HL7InstanceIdentifier, hl7_InstanceIdentifier.c_str());
- }
- OFStandard::snprintf(buf, sizeof(buf), "%ld", OFstatic_cast(long, opt_instance));
- if (result.good()) result = dataset->putAndInsertString(DCM_InstanceNumber, buf);
- dcmGenerateUniqueIdentifier(buf, SITE_INSTANCE_UID_ROOT);
- if (result.good()) result = dataset->putAndInsertString(DCM_StudyInstanceUID, opt_studyUID.c_str());
- if (result.good()) result = dataset->putAndInsertString(DCM_SeriesInstanceUID, opt_seriesUID.c_str());
- if (result.good()) result = dataset->putAndInsertString(DCM_SOPInstanceUID, buf);
- // set instance creation date and time
- OFString s;
- if (result.good()) result = DcmDate::getCurrentDate(s);
- if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate, s);
- if (result.good()) result = DcmTime::getCurrentTime(s);
- if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime, s);
- return result;
-}
-OFCondition DcmEncapsulatedDocument::applyOverrideKeys(DcmDataset *outputDset)
-{
- // replace specific keys by those in overrideKeys, copied from findscu
- OFListConstIterator(OFString) path = opt_overrideKeys.begin();
- OFListConstIterator(OFString) endOfList = opt_overrideKeys.end();
- OFCondition cond;
- DcmPathProcessor proc;
- while (path != endOfList)
- {
- cond = proc.applyPathWithValue(outputDset, *path);
- if (cond.bad())
+ if (result.bad())
{
- OFString err;
- err += "Bad override key/path: ";
- err += *path;
- err += ": ";
- err += cond.text();
- return makeOFCondition(OFM_dcmdata, 18, OF_error, err.c_str());
+ DCMDATA_ERROR("Error while creating DICOM header: " << result.text());
}
- path++;
- }
- return cond;
+ return result;
}
-void DcmEncapsulatedDocument::setOverrideKeys(const OFList<OFString> &ovkeys)
-{
- OFListConstIterator(OFString) it = ovkeys.begin();
- OFListConstIterator(OFString) end = ovkeys.end();
- while (it != end)
- {
- opt_overrideKeys.push_back(*it);
- it++;
- }
-}
-OFCondition DcmEncapsulatedDocument::saveFile(DcmFileFormat fileformat)
+OFCondition DcmEncapsulatedDocument::applyOverrideKeys()
{
- return fileformat.saveFile(opt_ofname, opt_oxfer, opt_oenctype, opt_oglenc,
- opt_opadenc, OFstatic_cast(Uint32, opt_filepad),
- OFstatic_cast(Uint32, opt_itempad));
-}
-
-OFString DcmEncapsulatedDocument::getInputFileName()
-{
- return opt_ifname;
+ DcmDataset *outputDset = dfile_.getDataset();
+ // replace specific keys by those in overrideKeys, copied from findscu
+ OFListConstIterator(OFString) path = overrideKeys_.begin();
+ OFListConstIterator(OFString) endOfList = overrideKeys_.end();
+ OFCondition cond;
+ DcmPathProcessor proc;
+ if (path != endOfList)
+ {
+ DCMDATA_DEBUG("Applying override keys from command line");
+ }
+ while (path != endOfList)
+ {
+ cond = proc.applyPathWithValue(outputDset, *path);
+ if (cond.bad())
+ {
+ OFString err;
+ err += "Bad override key/path: ";
+ err += *path;
+ err += ": ";
+ err += cond.text();
+ DCMDATA_ERROR(err.c_str());
+ return makeOFCondition(OFM_dcmdata, 18, OF_error, err.c_str());
+ }
+ path++;
+ }
+ return cond;
}
-void DcmEncapsulatedDocument::setInputFileName(OFString fName)
-{
- opt_ifname = fName;
-}
-OFString DcmEncapsulatedDocument::getOutputFileName()
+OFCondition DcmEncapsulatedDocument::saveFile()
{
- return opt_ofname;
-}
+ OFCondition result = dfile_.saveFile(
+ ofname_, oxfer_, oenctype_, oglenc_, opadenc_,
+ OFstatic_cast(Uint32, filepad_), OFstatic_cast(Uint32, itempad_));
-void DcmEncapsulatedDocument::setOutputFileName(OFString fName)
-{
- opt_ofname = fName;
+ if (result.bad())
+ {
+ DCMDATA_ERROR(result.text() << ": writing file: '" << ofname_ << "'");
+ }
+ return result;
}
-OFString DcmEncapsulatedDocument::getFileType()
-{
- return ftype;
-}
-void DcmEncapsulatedDocument::setFileType(OFString fType)
+OFString DcmEncapsulatedDocument::getInputFileName()
{
- ftype = fType;
+ return ifname_;
}
-E_TransferSyntax DcmEncapsulatedDocument::getTransferSyntax()
-{
- return opt_oxfer;
-}
-DcmEncapsulatedDocument::~DcmEncapsulatedDocument()
+OFString DcmEncapsulatedDocument::getOutputFileName()
{
+ return ofname_;
}
/*
*
- * Copyright (C) 1994-2022, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
makeOFConditionConst(EC_ElemLengthExceeds32BitField, OFM_dcmdata, 54, OF_error, "Length of element value exceeds maximum of 32-bit length field" );
makeOFConditionConst(EC_CannotWriteJsonNumber, OFM_dcmdata, 55, OF_error, "Cannot write 'nan' or 'inf' as JSON number" );
makeOFConditionConst(EC_CannotWriteJsonInlineBinary, OFM_dcmdata, 56, OF_error, "JSON InlineBinary encoding not supported for compressed pixel data" );
-makeOFConditionConst(EC_XMLParseError, OFM_dcmdata, 57, OF_error, "XML parse error" );
-makeOFConditionConst(EC_XMLValidationFailure, OFM_dcmdata, 58, OF_error, "XML validation failure" );
-makeOFConditionConst(EC_SOPClassMismatch, OFM_dcmdata, 59, OF_error, "SOP class mismatch" );
+makeOFConditionConst(EC_XMLParseError, OFM_dcmdata, 57, OF_error, "XML parse error" );
+makeOFConditionConst(EC_XMLValidationFailure, OFM_dcmdata, 58, OF_error, "XML validation failure" );
+makeOFConditionConst(EC_SOPClassMismatch, OFM_dcmdata, 59, OF_error, "SOP Class mismatch" );
makeOFConditionConst(EC_UnknownUIDName, OFM_dcmdata, 60, OF_error, "Unknown UID name: No mapping to UID value defined" );
-makeOFConditionConst(EC_CannotWriteStringAsJsonNumber, OFM_dcmdata, 61, OF_error, "Cannot write IS/DS string as JSON number" );
+makeOFConditionConst(EC_CannotWriteStringAsJSONNumber, OFM_dcmdata, 61, OF_error, "Cannot write IS/DS string as JSON number" );
+makeOFConditionConst(EC_CannotWriteBulkDataFile, OFM_dcmdata, 62, OF_error, "Cannot write bulk data file" );
+makeOFConditionConst(EC_CannotWriteJSONMultiframe, OFM_dcmdata, 63, OF_error, "JSON encoding not supported for encapsulated multi-frame pixel data" );
+makeOFConditionConst(EC_InvalidJSONType, OFM_dcmdata, 64, OF_error, "Invalid JSON type" );
+makeOFConditionConst(EC_InvalidJSONContent, OFM_dcmdata, 65, OF_error, "Invalid JSON content" );
+makeOFConditionConst(EC_BulkDataURINotSupported, OFM_dcmdata, 66, OF_error, "BulkDataURI not yet supported" );
+makeOFConditionConst(EC_UnsupportedURIType, OFM_dcmdata, 67, OF_error, "Unsupported URI type" );
+makeOFConditionConst(EC_CommandLineFailed, OFM_dcmdata, 68, OF_error, "Execution of command line failed" );
const unsigned short EC_CODE_CannotSelectCharacterSet = 35;
const unsigned short EC_CODE_CannotConvertCharacterSet = 36;
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
DcmFileFormat::DcmFileFormat()
: DcmSequenceOfItems(DCM_InternalUseTag),
- FileReadMode(ERM_autoDetect)
+ FileReadMode(ERM_autoDetect),
+ ImplementationClassUID(OFFIS_IMPLEMENTATION_CLASS_UID),
+ ImplementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME)
{
DcmMetaInfo *MetaInfo = new DcmMetaInfo();
DcmSequenceOfItems::itemList->insert(MetaInfo);
DcmFileFormat::DcmFileFormat(DcmDataset *dataset,
OFBool deepCopy)
: DcmSequenceOfItems(DCM_InternalUseTag),
- FileReadMode(ERM_autoDetect)
+ FileReadMode(ERM_autoDetect),
+ ImplementationClassUID(OFFIS_IMPLEMENTATION_CLASS_UID),
+ ImplementationVersionName(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME)
{
DcmMetaInfo *MetaInfo = new DcmMetaInfo();
DcmSequenceOfItems::itemList->insert(MetaInfo);
DcmFileFormat::DcmFileFormat(const DcmFileFormat &old)
: DcmSequenceOfItems(old),
- FileReadMode(old.FileReadMode)
+ FileReadMode(old.FileReadMode),
+ ImplementationClassUID(old.ImplementationClassUID),
+ ImplementationVersionName(old.ImplementationVersionName)
{
}
{
DcmSequenceOfItems::operator=(obj);
FileReadMode = obj.FileReadMode;
+ ImplementationClassUID = obj.ImplementationClassUID;
+ ImplementationVersionName = obj.ImplementationVersionName;
}
return *this;
// ********************************
-OFCondition DcmFileFormat::checkMetaHeaderValue(DcmMetaInfo *metainfo,
- DcmDataset *dataset,
- const DcmTagKey &atagkey,
- DcmObject *obj,
- const E_TransferSyntax oxfer,
- const E_FileWriteMode writeMode)
+OFCondition DcmFileFormat::checkMetaHeaderValue(
+ DcmMetaInfo *metainfo,
+ DcmDataset *dataset,
+ const DcmTagKey &atagkey,
+ DcmObject *obj,
+ const E_TransferSyntax oxfer,
+ const E_FileWriteMode writeMode) const
/*
* This function checks if a particular data element of the file meta information header is
* existent. If the element is not existent, it will be inserted. Additionally, this function
}
if (elem->ident() == EVR_UI)
{
- if ((writeMode == EWM_updateMeta) || (elem->getLength() == 0))
+ if ((writeMode == EWM_updateMeta) || (writeMode == EWM_createNewMeta) || (elem->getLength() == 0))
{
if (dataset->search(DCM_SOPClassUID, stack).good() && (stack.top()->ident() == EVR_UI))
{
}
if (elem->ident() == EVR_UI)
{
- if ((writeMode == EWM_updateMeta) || (elem->getLength() == 0))
+ if ((writeMode == EWM_updateMeta) || (writeMode == EWM_createNewMeta) || (elem->getLength() == 0))
{
if (dataset->search(DCM_SOPInstanceUID, stack).good() && (stack.top()->ident() == EVR_UI))
{
}
if (elem->ident() == EVR_UI)
{
- const char *uid = OFFIS_IMPLEMENTATION_CLASS_UID;
- OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(uid);
+ OFstatic_cast(DcmUniqueIdentifier *, elem)->putString(ImplementationClassUID.c_str());
}
}
else if (tag == DCM_ImplementationVersionName) // (0002,0013)
}
if (elem->ident() == EVR_SH)
{
- const char *uid = OFFIS_DTK_IMPLEMENTATION_VERSION_NAME;
- OFstatic_cast(DcmShortString *, elem)->putString(uid);
+ OFstatic_cast(DcmShortString *, elem)->putString(ImplementationVersionName.c_str());
}
}
else if ((tag == DCM_SourceApplicationEntityTitle) || // (0002,0016)
{
DCMDATA_WARN("DcmFileFormat: Meta Information Header is not updated!");
} else {
+ /* in the following, we want to make sure all elements of the meta header */
+ /* are existent in metinf and contain correct values */
+ DcmStack stack;
+
/* start with empty file meta information */
if (writeMode == EWM_createNewMeta)
+ {
+ /* search, and if present, store and remove the media storage SOP class and instance UID. */
+ metinf->search(DCM_MediaStorageSOPClassUID, stack, ESM_fromHere, OFFalse);
+ DcmElement *sopClassUID = metinf->remove(stack.top());
+ metinf->search(DCM_MediaStorageSOPInstanceUID, stack, ESM_fromHere, OFFalse);
+ DcmElement *sopInstanceUID = metinf->remove(stack.top());
+
+ /* clear the meta-header and the search stack */
metinf->clear();
+ stack.clear();
- /* in the following, we want to make sure all elements of the meta header */
- /* are existent in metinf and contain correct values */
- DcmStack stack;
+ /* re-insert SOP class UID and SOP instance UID */
+ if (sopClassUID) metinf->insert(sopClassUID);
+ if (sopInstanceUID) metinf->insert(sopInstanceUID);
+ }
/* DCM_FileMetaInformationGroupLength */
metinf->search(DCM_FileMetaInformationGroupLength, stack, ESM_fromHere, OFFalse);
// remember the parent
dataset->setParent(this);
}
+
+ // initialize dataset transfer syntax members
+ // to make sure the values are correct even if the dataset is empty
+ dataset->initializeXfer(newxfer);
+
// check whether to read the dataset at all
if (FileReadMode != ERM_metaOnly)
{
* in the file meta information header.
*/
{
+ /* write as dataset (without meta header) */
+ if (writeMode == EWM_dataset)
+ {
+ return getDataset()->write(outStream, oxfer, enctype, wcache, glenc,
+ padenc, padlen, subPadlen, instanceLength);
+ }
/* if the transfer state of this is not initialized, this is an illegal call */
if (getTransferState() == ERW_notInitialized)
errorFlag = EC_IllegalCall;
const Uint32 subPadLength,
const E_FileWriteMode writeMode)
{
+ /* save as dataset (without meta header) */
if (writeMode == EWM_dataset)
{
return getDataset()->saveFile(fileName, writeXfer, encodingType, groupLength,
{
errorFlag = EC_Normal;
DcmMetaInfo *meta = NULL;
- if (itemList->seek_to(0) != NULL && itemList->get()->ident() == EVR_metainfo)
- meta = OFstatic_cast(DcmMetaInfo *, itemList->get());
+ // the meta information is the first item
+ DcmObject *object = itemList->seek(ELP_first);
+ if (object != NULL && object->ident() == EVR_metainfo)
+ meta = OFstatic_cast(DcmMetaInfo *, object);
else
errorFlag = EC_IllegalCall;
return meta;
{
errorFlag = EC_Normal;
DcmDataset *data = NULL;
- if (itemList->seek_to(1) != NULL && itemList->get()->ident() == EVR_dataset)
- data = OFstatic_cast(DcmDataset *, itemList->get());
+ // the dataset is the last item
+ DcmObject *object = itemList->seek(ELP_last);
+ if (object != NULL && object->ident() == EVR_dataset)
+ data = OFstatic_cast(DcmDataset *, object);
else
errorFlag = EC_IllegalCall;
return data;
{
errorFlag = EC_Normal;
DcmDataset *data = NULL;
- if (itemList->seek_to(1) != NULL && itemList->get()->ident() == EVR_dataset)
+ // the dataset is the last item
+ DcmObject *object = itemList->seek(ELP_last);
+ if (object != NULL && object->ident() == EVR_dataset)
{
data = OFstatic_cast(DcmDataset *, itemList->remove());
// forget about the parent
// the DICOM defined term "ISO_IR 192" is used for "UTF-8"
return convertCharacterSet("ISO_IR 192", 0 /*flags*/);
}
+
+void DcmFileFormat::setImplementationClassUID(const OFString& implementationClassUID)
+{
+ ImplementationClassUID = implementationClassUID;
+}
+
+void DcmFileFormat::setImplementationVersionName(const OFString& implementationVersionName)
+{
+ ImplementationVersionName = implementationVersionName;
+ if (ImplementationVersionName.length() > 16)
+ {
+ DCMDATA_WARN("DcmFileFormat: implementation version name too long");
+ ImplementationVersionName.erase(16);
+ }
+}
/*
*
- * Copyright (C) 2002-2021, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcerror.h"
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
/*
*
- * Copyright (C) 2002-2021, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcerror.h"
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
/*
*
- * Copyright (C) 2002-2010, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* (where PDVs always have even length).
* Everything else generates a warning.
*/
- DCMDATA_WARN("zlib: " << OFstatic_cast(ulong, count-1) << " pending input bytes in buffer.");
+ DCMDATA_WARN("DcmZLibInputFilter: " << OFstatic_cast(unsigned long, count-1) << " pending input bytes in buffer");
}
}
#endif
* (where PDVs always have even length).
* Everything else generates a warning.
*/
- DCMDATA_WARN("zlib: " << OFstatic_cast(ulong, count-1) << " pending input bytes in buffer.");
+ DCMDATA_WARN("DcmZLibInputFilter: " << OFstatic_cast(unsigned long, count-1) << " pending input bytes in buffer");
}
}
#endif
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
swapIfNecessary(gLocalByteOrder, byteOrder, &elementTag, 2, 2);
// tag has been read
bytesRead = 4;
+ OFString readVR;
DcmTag newTag(groupTag, elementTag);
DcmEVR newEVR = newTag.getEVR();
// check whether tag is private
- OFBool isPrivate = groupTag & 1;
+ const OFBool isPrivate = groupTag & 1;
/* if the transfer syntax which was passed is an explicit VR syntax and if the current */
/* item is not a delimitation item (note that delimitation items do not have a VR), go */
/* read 2 bytes */
inStream.read(vrstr, 2);
+ readVR = vrstr;
/* create a corresponding DcmVR object */
DcmVR vr(vrstr);
if ((vrSize > 1) && (valueLength % vrSize != 0))
{
/* warning is only reported for standard, fixed-size VRs that require more than 1 byte per value */
- DCMDATA_WARN("DcmItem: Length of element " << newTag << " is not a multiple of " << vrSize << " (VR=" << vr.getVRName() << ")");
+ if (valueLength == DCM_UndefinedLength)
+ {
+ /* check whether the VR supports undefined length for the length field */
+ if (!vr.supportsUndefinedLength())
+ {
+ DCMDATA_WARN("DcmItem: Dubious use of undefined length for element " << newTag
+ << " with VR=" << vr.getVRName());
+ }
+ } else {
+ DCMDATA_WARN("DcmItem: Length of element " << newTag << " is not a multiple of " << vrSize
+ << " (VR=" << vr.getVRName() << ")");
+ }
}
}
+ /* check whether the correct VR is used for PixelData element in encapsulated format */
+ if ((newTag == DCM_PixelData) && xferSyn.usesEncapsulatedFormat() &&
+ (valueLength == DCM_UndefinedLength) && (readVR != "OB") /* this is the VR that was read */)
+ {
+ DCMDATA_WARN("DcmItem: Wrong VR for encapsulated PixelData " << newTag
+ << ", should be 'OB' instead of '" << readVR << "'");
+ }
+
/* if the value in the length field is odd, print an error message */
if ((valueLength & 1) && (valueLength != DCM_UndefinedLength))
{
}
-OFCondition DcmItem::findAndGetString(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetString(const DcmTagKey &tagKey,
const char *&value,
const OFBool searchIntoSub)
{
}
-OFCondition DcmItem::findAndGetString(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetString(const DcmTagKey &tagKey,
const char *&value,
Uint32 &length,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetOFString(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetOFString(const DcmTagKey &tagKey,
OFString &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetOFStringArray(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetOFStringArray(const DcmTagKey &tagKey,
OFString &value,
const OFBool searchIntoSub)
{
}
-OFCondition DcmItem::findAndGetUint8(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint8(const DcmTagKey &tagKey,
Uint8 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetUint8Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint8Array(const DcmTagKey &tagKey,
const Uint8 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetUint16(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint16(const DcmTagKey &tagKey,
Uint16 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetUint16Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint16Array(const DcmTagKey &tagKey,
const Uint16 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetSint16(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetSint16(const DcmTagKey &tagKey,
Sint16 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetSint16Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetSint16Array(const DcmTagKey &tagKey,
const Sint16 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetUint32(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint32(const DcmTagKey &tagKey,
Uint32 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetUint32Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint32Array(const DcmTagKey &tagKey,
const Uint32 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetSint32(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetSint32(const DcmTagKey &tagKey,
Sint32 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetSint32Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetSint32Array(const DcmTagKey &tagKey,
const Sint32 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetUint64(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint64(const DcmTagKey &tagKey,
Uint64 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetUint64Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetUint64Array(const DcmTagKey &tagKey,
const Uint64 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetSint64(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetSint64(const DcmTagKey &tagKey,
Sint64 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetSint64Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetSint64Array(const DcmTagKey &tagKey,
const Sint64 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetLongInt(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetLongInt(const DcmTagKey &tagKey,
long int &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetFloat32(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetFloat32(const DcmTagKey &tagKey,
Float32 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetFloat32Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetFloat32Array(const DcmTagKey &tagKey,
const Float32 *&value,
unsigned long *count,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetFloat64(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetFloat64(const DcmTagKey &tagKey,
Float64 &value,
const unsigned long pos,
const OFBool searchIntoSub)
}
-OFCondition DcmItem::findAndGetFloat64Array(const DcmTagKey& tagKey,
+OFCondition DcmItem::findAndGetFloat64Array(const DcmTagKey &tagKey,
const Float64 *&value,
unsigned long *count,
const OFBool searchIntoSub)
/* --- findOrCreate functions: find an element or create a new one --- */
-OFCondition DcmItem::findOrCreateSequenceItem(const DcmTag& seqTag,
+OFCondition DcmItem::findOrCreateSequenceItem(const DcmTag &seqTag,
DcmItem *&item,
const signed long itemNum)
{
/* --- putAndInsert functions: put value and insert new element --- */
-OFCondition DcmItem::putAndInsertString(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertString(const DcmTag &tag,
const char *value,
const OFBool replaceOld)
{
}
-OFCondition DcmItem::putAndInsertString(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertString(const DcmTag &tag,
const char *value,
const Uint32 length,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertOFStringArray(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertOFStringArray(const DcmTag &tag,
const OFString &value,
const OFBool replaceOld)
{
}
-OFCondition DcmItem::putAndInsertUint8Array(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertUint8Array(const DcmTag &tag,
const Uint8 *value,
const unsigned long count,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertUint16(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertUint16(const DcmTag &tag,
const Uint16 value,
const unsigned long pos,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertUint16Array(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertUint16Array(const DcmTag &tag,
const Uint16 *value,
const unsigned long count,
const OFBool replaceOld)
case EVR_AT:
elem = new DcmAttributeTag(tag);
break;
+ case EVR_US:
+ elem = new DcmUnsignedShort(tag);
+ break;
case EVR_lt:
case EVR_OW:
elem = new DcmOtherByteOtherWord(tag);
break;
- case EVR_US:
- elem = new DcmUnsignedShort(tag);
- break;
case EVR_ox:
/* special handling */
if (tag == DCM_PixelData)
}
-OFCondition DcmItem::putAndInsertSint16(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertSint16(const DcmTag &tag,
const Sint16 value,
const unsigned long pos,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertSint16Array(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertSint16Array(const DcmTag &tag,
const Sint16 *value,
const unsigned long count,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertUint32(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertUint32(const DcmTag &tag,
const Uint32 value,
const unsigned long pos,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertUint32Array(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertUint32Array(const DcmTag &tag,
const Uint32 *value,
const unsigned long count,
const OFBool replaceOld)
DcmElement *elem = NULL;
switch(tag.getEVR())
{
- case EVR_OL:
- elem = new DcmOtherLong(tag);
- break;
case EVR_UL:
elem = new DcmUnsignedLong(tag);
break;
+ case EVR_OL:
+ elem = new DcmOtherLong(tag);
+ break;
case EVR_UNKNOWN:
/* Unknown VR, e.g. tag not found in data dictionary */
status = EC_UnknownVR;
}
-OFCondition DcmItem::putAndInsertSint32(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertSint32(const DcmTag &tag,
const Sint32 value,
const unsigned long pos,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertSint32Array(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertSint32Array(const DcmTag &tag,
const Sint32 *value,
const unsigned long count,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertFloat32(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertUint64(const DcmTag &tag,
+ const Uint64 value,
+ const unsigned long pos,
+ const OFBool replaceOld)
+{
+ OFCondition status = EC_Normal;
+ /* create new element */
+ DcmElement *elem = NULL;
+ switch(tag.getEVR())
+ {
+ case EVR_UV:
+ elem = new DcmUnsigned64bitVeryLong(tag);
+ break;
+ case EVR_OV:
+ elem = new DcmOther64bitVeryLong(tag);
+ break;
+ case EVR_UNKNOWN:
+ /* Unknown VR, e.g. tag not found in data dictionary */
+ status = EC_UnknownVR;
+ break;
+ default:
+ status = EC_IllegalCall;
+ break;
+ }
+ if (elem != NULL)
+ {
+ /* put value */
+ status = elem->putUint64(value, pos);
+ /* insert into dataset/item */
+ if (status.good())
+ status = insert(elem, replaceOld);
+ /* could not be inserted, therefore, delete it immediately */
+ if (status.bad())
+ delete elem;
+ } else if (status.good())
+ status = EC_MemoryExhausted;
+ return status;
+}
+
+
+OFCondition DcmItem::putAndInsertUint64Array(const DcmTag &tag,
+ const Uint64 *value,
+ const unsigned long count,
+ const OFBool replaceOld)
+{
+ OFCondition status = EC_Normal;
+ /* create new element */
+ DcmElement *elem = NULL;
+ switch(tag.getEVR())
+ {
+ case EVR_UV:
+ elem = new DcmUnsigned64bitVeryLong(tag);
+ break;
+ case EVR_OV:
+ elem = new DcmOther64bitVeryLong(tag);
+ break;
+ case EVR_UNKNOWN:
+ /* Unknown VR, e.g. tag not found in data dictionary */
+ status = EC_UnknownVR;
+ break;
+ default:
+ status = EC_IllegalCall;
+ break;
+ }
+ if (elem != NULL)
+ {
+ /* put value */
+ status = elem->putUint64Array(value, count);
+ /* insert into dataset/item */
+ if (status.good())
+ status = insert(elem, replaceOld);
+ /* could not be inserted, therefore, delete it immediately */
+ if (status.bad())
+ delete elem;
+ } else if (status.good())
+ status = EC_MemoryExhausted;
+ return status;
+}
+
+
+OFCondition DcmItem::putAndInsertSint64(const DcmTag &tag,
+ const Sint64 value,
+ const unsigned long pos,
+ const OFBool replaceOld)
+{
+ OFCondition status = EC_Normal;
+ /* create new element */
+ DcmElement *elem = NULL;
+ switch(tag.getEVR())
+ {
+ case EVR_SV:
+ elem = new DcmSigned64bitVeryLong(tag);
+ break;
+ case EVR_UNKNOWN:
+ /* Unknown VR, e.g. tag not found in data dictionary */
+ status = EC_UnknownVR;
+ break;
+ default:
+ status = EC_IllegalCall;
+ break;
+ }
+ if (elem != NULL)
+ {
+ /* put value */
+ status = elem->putSint64(value, pos);
+ /* insert into dataset/item */
+ if (status.good())
+ status = insert(elem, replaceOld);
+ /* could not be inserted, therefore, delete it immediately */
+ if (status.bad())
+ delete elem;
+ } else if (status.good())
+ status = EC_MemoryExhausted;
+ return status;
+}
+
+
+OFCondition DcmItem::putAndInsertSint64Array(const DcmTag &tag,
+ const Sint64 *value,
+ const unsigned long count,
+ const OFBool replaceOld)
+{
+ OFCondition status = EC_Normal;
+ /* create new element */
+ DcmElement *elem = NULL;
+ switch(tag.getEVR())
+ {
+ case EVR_SV:
+ elem = new DcmSigned64bitVeryLong(tag);
+ break;
+ case EVR_UNKNOWN:
+ /* Unknown VR, e.g. tag not found in data dictionary */
+ status = EC_UnknownVR;
+ break;
+ default:
+ status = EC_IllegalCall;
+ break;
+ }
+ if (elem != NULL)
+ {
+ /* put value */
+ status = elem->putSint64Array(value, count);
+ /* insert into dataset/item */
+ if (status.good())
+ status = insert(elem, replaceOld);
+ /* could not be inserted, therefore, delete it immediately */
+ if (status.bad())
+ delete elem;
+ } else if (status.good())
+ status = EC_MemoryExhausted;
+ return status;
+}
+
+
+OFCondition DcmItem::putAndInsertFloat32(const DcmTag &tag,
const Float32 value,
const unsigned long pos,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertFloat32Array(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertFloat32Array(const DcmTag &tag,
const Float32 *value,
const unsigned long count,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertFloat64(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertFloat64(const DcmTag &tag,
const Float64 value,
const unsigned long pos,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertFloat64Array(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertFloat64Array(const DcmTag &tag,
const Float64 *value,
const unsigned long count,
const OFBool replaceOld)
}
-OFCondition DcmItem::putAndInsertTagKey(const DcmTag& tag,
+OFCondition DcmItem::putAndInsertTagKey(const DcmTag &tag,
const DcmTagKey &value,
const unsigned long pos,
const OFBool replaceOld)
// ********************************
-OFCondition DcmItem::insertEmptyElement(const DcmTag& tag,
+OFCondition DcmItem::insertEmptyElement(const DcmTag &tag,
const OFBool replaceOld)
{
OFCondition status = EC_Normal;
// delete Specific Character Set (0008,0005) data element (type 1C)
if (findAndDeleteElement(DCM_SpecificCharacterSet, OFFalse /*allOccurrences*/, OFFalse /*searchIntoSub*/).good())
{
- DCMDATA_DEBUG("DcmItem::convertCharacterSet() deleted element SpecificCharacterSet "
+ DCMDATA_DEBUG("DcmItem::updateSpecificCharacterSet() deleted element SpecificCharacterSet "
<< DCM_SpecificCharacterSet << " during the conversion to " << encoding << " encoding");
}
} else {
- DCMDATA_DEBUG("DcmItem::convertCharacterSet() updating value of element SpecificCharacterSet "
+ DCMDATA_DEBUG("DcmItem::updateSpecificCharacterSet() updating value of element SpecificCharacterSet "
<< DCM_SpecificCharacterSet << " to '" << toCharset << "'");
// update/set value of Specific Character Set (0008,0005) if needed
status = putAndInsertOFStringArray(DCM_SpecificCharacterSet, toCharset);
if (dcmIgnoreParsingErrors.get())
{
// ignore parse error, keep VR unchanged
- DCMDATA_WARN("DcmItem: VOI LUT Sequence with VR=OW and explicit length encountered.");
+ DCMDATA_WARN("DcmItem: VOI LUT Sequence with VR=OW and explicit length encountered");
newElement = new DcmOtherByteOtherWord(tag, length);
}
else
{
// bail out with an error
- DCMDATA_ERROR("DcmItem: VOI LUT Sequence with VR=OW and explicit length encountered.");
+ DCMDATA_ERROR("DcmItem: VOI LUT Sequence with VR=OW and explicit length encountered");
l_error = EC_VOI_LUT_OBOW;
}
}
// special handling for private pixel data (compressed or uncompressed)
if (newTag.getEVR() == EVR_px)
{
- DCMDATA_WARN("Found private element " << tag << " with VR " << tag.getVRName()
- << " and undefined length, reading a pixel sequence according to data dictionary");
+ if (length == DCM_UndefinedLength)
+ {
+ DCMDATA_WARN("DcmItem: Found private element " << tag << " with VR=" << tag.getVRName()
+ << " and undefined length, reading a pixel sequence according to data dictionary");
+ }
newElement = new DcmPixelData(tag, length);
}
}
newTag.setVR(DcmVR(EVR_SQ)); // on writing we will handle this element as SQ, not UN
if (dcmEnableCP246Support.get())
{
- DCMDATA_WARN("Found element " << newTag << " with VR UN and undefined length, "
+ DCMDATA_WARN("DcmItem: Found element " << newTag << " with VR=UN and undefined length, "
<< "reading a sequence with transfer syntax LittleEndianImplicit (CP-246)");
} else {
- DCMDATA_WARN("Found element " << newTag << " with VR UN and undefined length");
+ DCMDATA_WARN("DcmItem: Found element " << newTag << " with VR=UN and undefined length");
}
newElement = new DcmSequenceOfItems(newTag, length, dcmEnableCP246Support.get());
} else {
/*
*
- * Copyright (C) 2016-2023, OFFIS e.V.
+ * Copyright (C) 2016-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcjson.h"
#include "dcmtk/ofstd/ofdefine.h"
#include "dcmtk/ofstd/ofstring.h"
+#include "dcmtk/ofstd/offile.h"
+#include "dcmtk/ofstd/ofsha256.h"
+#include "dcmtk/ofstd/ofstream.h"
+#include "dcmtk/dcmdata/dctypes.h"
+#include "dcmtk/dcmdata/dcerror.h"
#include <cassert>
out << "\\f";
break;
default:
- //escapes all other control characters
+ // escapes all other control characters
if (c >= '\0' && c < ' ')
{
out << "\\u" << STD_NAMESPACE hex
// These are permitted in DICOM but not in JSON.
size_t pos;
while (OFString_npos != (pos = value.find('+')))
- value.erase(pos,1);
+ value.erase(pos,1);
// check if the first character is a minus sign.
// if so, remove it and set "minus" to true
// with a period
if (OFString_npos != (pos = value.find('.')))
{
- if (pos == value.length() -1)
- {
- // number ends with a period. Add a zero
- value.append("0");
- }
- else if ((value[pos+1] < '0') || (value[pos+1] > '9'))
- {
- // no digit after period. Insert a zero
- value.insert(pos+1, "0");
- }
+ if (pos == value.length() -1)
+ {
+ // number ends with a period. Add a zero
+ value.append("0");
+ }
+ else if ((value[pos+1] < '0') || (value[pos+1] > '9'))
+ {
+ // no digit after period. Insert a zero
+ value.insert(pos+1, "0");
+ }
}
-
}
// Formats the number to JSON standard as IntegerString
void DcmJsonFormat::normalizeIntegerString(OFString &value)
{
// remove all plus characters that may occur in the string.
- // These are permitted in DICOM but not in Json.
+ // These are permitted in DICOM but not in JSON.
size_t pos;
while (OFString_npos != (pos = value.find('+')))
- value.erase(pos,1);
+ value.erase(pos,1);
OFBool minus = OFFalse;
out << "," << newline() << indent();
}
-// Method for holding and determine if BulkDataURI should be printed.
-// This also manipulate uri String, if BulkDataURI should be printed.
-OFBool DcmJsonFormat::asBulkDataURI(const DcmTagKey& /*tag*/, OFString& /*uri*/)
+OFBool DcmJsonFormat::asBulkDataURI(const DcmTagKey& /*tag*/, Uint32 len) const
+{
+ // return OFFalse if bulk data is disabled
+ if (minBulkDataSize < 0) return OFFalse;
+
+ // return OFFalse if the attribute value is too small
+ size_t minSize = (OFstatic_cast(size_t, minBulkDataSize));
+ if ((minSize << 10) > len) return OFFalse;
+
+ return OFTrue;
+}
+
+void DcmJsonFormat::getBulkDataDirectory(OFString& directory) const
+{
+ directory = bulkDataDirectory;
+}
+
+void DcmJsonFormat::getBulkDataURIPrefix(OFString& prefix) const
+{
+ prefix = bulkDataURIPrefix;
+}
+
+void DcmJsonFormat::setMinBulkSize(ssize_t min_bulk_size)
{
- return OFFalse;
+ minBulkDataSize = min_bulk_size;
}
-//Class for formatted output
+void DcmJsonFormat::setBulkURIPrefix(const char *bulk_uri_prefix)
+{
+ if (bulk_uri_prefix)
+ {
+ bulkDataURIPrefix = bulk_uri_prefix;
+
+ // if the URI prefix does not end with "/", silently add this character
+ if ((bulkDataURIPrefix.length() > 0) && (bulkDataURIPrefix[bulkDataURIPrefix.length()-1] != '/'))
+ {
+ bulkDataURIPrefix.append("/");
+ }
+ }
+ else bulkDataURIPrefix = "";
+}
+
+void DcmJsonFormat::setBulkDir(const char *bulk_dir)
+{
+ if (bulk_dir)
+ {
+ bulkDataDirectory = bulk_dir;
+ }
+ else bulkDataDirectory = ".";
+
+ // if the directory name does not end with a path separator, silently add one
+ if ((bulkDataDirectory.length() > 0) && (bulkDataDirectory[bulkDataDirectory.length()-1] != '/') && (bulkDataDirectory[bulkDataDirectory.length()-1] != PATH_SEPARATOR))
+ {
+ bulkDataDirectory.append(1, PATH_SEPARATOR);
+ }
+}
+
+
+OFCondition DcmJsonFormat::writeBulkData(
+ STD_NAMESPACE ostream &out,
+ const DcmTagKey& /*tagkey*/,
+ Uint32 len,
+ Uint8 *byteValues,
+ const char *extension)
+{
+ /* for an empty value field, we do not need to do anything */
+ if (len > 0)
+ {
+ OFString bulkDataURI;
+ getBulkDataURIPrefix(bulkDataURI);
+
+ /* compute SHA-256 checksum */
+ size_t vallen = OFstatic_cast(size_t, len);
+ OFSHA256 sha256;
+ Uint8 hash[32];
+ sha256.update(byteValues, vallen);
+ sha256.final(hash);
+
+ /* determine filename and path */
+ OFString bulkname;
+ char hashstring[3];
+ for (int i=0; i < 32; ++i)
+ {
+ OFStandard::snprintf(hashstring, sizeof(hashstring), "%02x", hash[i]);
+ bulkname.append(hashstring);
+ }
+ if (extension) bulkname.append(extension);
+
+ OFString bulkpath;
+ getBulkDataDirectory(bulkpath);
+
+ /* bulkpath already ends with a path separator, just add the file name */
+ bulkpath.append(bulkname);
+
+ /* check if file already exists. In this case, the file content is the same
+ * we would create now since the SHA-256 checksum is the same. So we can just
+ * use the existing file.
+ */
+ if (! OFStandard::fileExists(bulkpath))
+ {
+ OFFile bulkfile;
+ if (! bulkfile.fopen(bulkpath.c_str(), "wb"))
+ {
+ DCMDATA_ERROR("Unable to create bulk data file '" << bulkpath << "'");
+ return EC_CannotWriteBulkDataFile;
+ }
+ if (vallen != bulkfile.fwrite(byteValues, 1, vallen))
+ {
+ DCMDATA_ERROR("Unable to write bulk data to file '" << bulkpath << "'");
+ return EC_CannotWriteBulkDataFile;
+ }
+ if (bulkfile.fclose())
+ {
+ DCMDATA_ERROR("Unable to close bulk data file '" << bulkpath << "'");
+ return EC_CannotWriteBulkDataFile;
+ }
+ }
+
+ /* return defined BulkDataURI associated with `tagKey` */
+ printBulkDataURIPrefix(out);
+ bulkDataURI.append(bulkname);
+ DcmJsonFormat::printString(out, bulkDataURI);
+ }
+
+ return EC_Normal;
+}
+
+
+OFCondition DcmJsonFormat::writeBinaryAttribute(
+ STD_NAMESPACE ostream &out,
+ const DcmTagKey& tagkey,
+ Uint32 len,
+ Uint8 *byteValues,
+ const char *extension)
+{
+ OFCondition result = EC_Normal;
+
+ /* for an empty value field, we do not need to do anything */
+ if (len > 0)
+ {
+ if (asBulkDataURI(tagkey, len))
+ {
+ result = writeBulkData(out, tagkey, len, byteValues, extension);
+ }
+ else
+ {
+ /* encode binary data as Base64 */
+ printInlineBinaryPrefix(out);
+ out << "\"";
+ /* adjust byte order to little endian */
+ OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, len));
+ out << "\"";
+ }
+ }
+
+ return result;
+}
+
+
+// --------------------------------------------------------------------------
+// Class for formatted output
+// --------------------------------------------------------------------------
+
DcmJsonFormatPretty::DcmJsonFormatPretty(const OFBool printMetaInfo)
: DcmJsonFormat(printMetaInfo)
, m_IndentionLevel(0)
{
-
}
void DcmJsonFormatPretty::printIndention(STD_NAMESPACE ostream& out)
return " ";
}
+// --------------------------------------------------------------------------
+// Class for unformatted output
+// --------------------------------------------------------------------------
-//Class for unformatted output
DcmJsonFormatCompact::DcmJsonFormatCompact(const OFBool printMetaInfo)
: DcmJsonFormat(printMetaInfo)
{
-
}
void DcmJsonFormatCompact::printIndention(STD_NAMESPACE ostream& /*out*/)
-{}
+{
+}
void DcmJsonFormatCompact::increaseIndention()
-{}
+{
+}
void DcmJsonFormatCompact::decreaseIndention()
-{}
+{
+}
OFString DcmJsonFormatCompact::newline()
{
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Tingyan Xu, Marco Eichelberg
+ *
+ * Purpose: Class for converting JSON DICOM documents to binary DICOM files
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/dcmdata/dcjsonrd.h"
+#include "dcmtk/ofstd/ofcond.h" /* for class OFCondition */
+#include "dcmtk/ofstd/offile.h" /* for class OFFile */
+#include "dcmtk/dcmdata/dcerror.h" /* for dcmdata logger macros */
+#include "dcmtk/dcmdata/dcfilefo.h" /* for class DcmFileFormat */
+#include "dcmtk/dcmdata/dcmetinf.h"
+#include "dcmtk/dcmdata/dcdeftag.h" /* for tag keys */
+#include "dcmtk/dcmdata/dcswap.h"
+#include "dcmtk/dcmdata/dcvrov.h" /* for DcmOther64bitVeryLong */
+
+#include <climits> /* for INT_MAX */
+
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+// Private creator identification string for files
+// containing a list of datasets as a private sequence
+#define JSON2DCM_PRIVATE_RESERVATION "JSON2DCM_LIST_OF_DATASETS"
+
+// Begin with a 1 MByte buffer when reading from stdin.
+// Buffer size will increase if necessary.
+#define JSON2DCM_STDIN_BLOCKSIZE 1048576
+
+
+DcmJSONReader::DcmJSONReader()
+: jsonDataset_(NULL)
+, jsonDatasetLen_(0)
+, tokenArray_(NULL)
+, tokenNumber_(0)
+, ignoreBulkdataURIPolicy_(OFFalse)
+, stopOnErrorPolicy_(OFTrue)
+, ignoreMetaInfoPolicy_(OFFalse)
+, arrayHandlingPolicy_(-1)
+, xferSyntax_(EXS_LittleEndianExplicit)
+, permittedBulkdataDirs_()
+{
+}
+
+
+DcmJSONReader::~DcmJSONReader()
+{
+ clear();
+}
+
+
+void DcmJSONReader::clear()
+{
+ delete[] jsonDataset_;
+ jsonDataset_ = NULL;
+ delete[] tokenArray_;
+ tokenArray_ = NULL;
+ jsonDatasetLen_ = 0;
+ tokenNumber_ = 0;
+}
+
+
+OFCondition DcmJSONReader::readJSONFile(const char *ifname)
+{
+ if (NULL == ifname) return EC_IllegalParameter;
+
+ OFFile jsonFile;
+ if (! jsonFile.fopen(ifname, "rb"))
+ {
+ OFString s("(unknown error code)");
+ jsonFile.getLastErrorString(s);
+ DCMDATA_ERROR("failed to open JSON file '" << ifname << "': " << s);
+ return makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str());
+ }
+
+ // obtain file size
+ const size_t len = OFStandard::getFileSize(ifname);
+ char *jsonString = new (std::nothrow) char[len + 1];
+ if (jsonString == NULL)
+ {
+ DCMDATA_ERROR("out of memory: failed to allocate buffer for JSON file");
+ return EC_MemoryExhausted;
+ }
+
+ // read the whole file to buffer
+ jsonString[len] = '\0';
+ size_t res = jsonFile.fread(jsonString, 1, len);
+ jsonFile.fclose();
+ if (res != len)
+ {
+ OFString s("(unknown error code)");
+ jsonFile.getLastErrorString(s);
+ delete[] jsonString;
+ return makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str());
+ }
+
+ // file was successfully read into buffer. Store the result, and in the process,
+ // clear the token array which is now invalid
+ clear();
+ jsonDataset_ = jsonString;
+ jsonDatasetLen_ = len;
+
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::readJSONFromStdin()
+{
+ size_t bufSize = JSON2DCM_STDIN_BLOCKSIZE;
+ size_t bufFree;
+ size_t bytesInBuffer = 0;
+ size_t readResult;
+ char *jsonString = NULL;;
+ char *oldBuf = NULL;
+ char *writePtr;
+ do
+ {
+ if (jsonString == NULL) jsonString = new (std::nothrow) char[bufSize+1];
+ if (jsonString == NULL)
+ {
+ DCMDATA_ERROR("out of memory: failed to allocate buffer for reading JSON dataset from stdin");
+ delete[] oldBuf;
+ return EC_MemoryExhausted;
+ }
+ if (oldBuf)
+ {
+ memmove(jsonString, oldBuf, bytesInBuffer);
+ delete[] oldBuf;
+ oldBuf = NULL;
+ }
+ writePtr = jsonString + bytesInBuffer;
+ bufFree = bufSize - bytesInBuffer;
+ readResult = fread(writePtr, 1, bufFree, stdin);
+ bytesInBuffer += readResult;
+ bufFree -= readResult;
+ if ((! feof(stdin)) && (bufFree == 0))
+ {
+ // we need more buffer. Double the size.
+ oldBuf = jsonString;
+ jsonString = NULL;
+ bufSize *= 2;
+ }
+ else if (feof(stdin))
+ {
+ jsonString[bytesInBuffer] = '\0';
+
+ // dataset was successfully read into buffer. Store the result, and in the process,
+ // clear the token array which is now invalid
+ clear();
+ jsonDataset_ = jsonString;
+ jsonDatasetLen_ = bytesInBuffer;
+ return EC_Normal;
+ }
+ } while (OFTrue);
+}
+
+
+OFCondition DcmJSONReader::reserveTokens()
+{
+ if ((NULL == jsonDataset_) || (jsonDatasetLen_ < 2))
+ return EC_IllegalCall;
+
+ OFJsmnParser jsmnParser;
+ jsmn_init(&jsmnParser);
+ int tokenNum = jsmn_parse(&jsmnParser, jsonDataset_, jsonDatasetLen_, NULL, 0);
+
+ if (tokenNum <= 0)
+ return EC_InvalidJSONContent;
+
+ // delete old token array, if still present
+ tokenNumber_ = 0;
+ delete[] tokenArray_;
+
+ // allocate one additional token
+ tokenArray_ = new (std::nothrow) OFJsmnToken[tokenNum+1];
+ if (NULL == tokenArray_)
+ {
+ DCMDATA_ERROR("out of memory: failed to allocate JSON token array");
+ return EC_MemoryExhausted;
+ }
+
+ // initialize token array with zeroes
+ memset(tokenArray_, 0, tokenNum * sizeof(OFJsmnToken));
+
+ // fill dummy token at the end of the array with values
+ // that allow the loop in parseElement() to reliably terminate
+ tokenArray_[tokenNum].start = INT_MAX;
+ tokenArray_[tokenNum].end = INT_MAX;
+ tokenArray_[tokenNum].size = 0;
+
+ // finally, store number of tokens
+ tokenNumber_ = tokenNum;
+
+ DCMDATA_TRACE("JSMN tokens reserved: " << tokenNum);
+ return EC_Normal;
+}
+
+
+void DcmJSONReader::getTokenContent(OFString& value, OFJsmnTokenPtr t)
+{
+ int size = t->end - t->start;
+
+ // remember the character immediately following the token
+ char c = jsonDataset_[t->start+size];
+
+ // convert the token string to a null terminated C string
+ jsonDataset_[t->start+size] = '\0';
+
+ // copy token string into output parameter
+ value = jsonDataset_ + t->start;
+
+ // restore array
+ jsonDataset_[t->start+size] = c;
+ return;
+}
+
+
+OFCondition DcmJSONReader::dumpJSONTokenArray()
+{
+ if ((NULL == tokenArray_) || (tokenNumber_ < 1))
+ return EC_IllegalCall;
+
+ const char *json_type;
+ OFString json_value;
+ fprintf(stderr, "============================== BEGIN JSON DUMP ==============================\n");
+ for (int i=0; i < tokenNumber_; ++i)
+ {
+ switch (tokenArray_[i].type)
+ {
+ case JSMN_OBJECT:
+ json_type = "object, size=";
+ break;
+ case JSMN_ARRAY:
+ json_type = "array, size=";
+ break;
+ case JSMN_STRING:
+ json_type = "string, size=";
+ break;
+ case JSMN_PRIMITIVE:
+ json_type = "primitive, size=";
+ break;
+ case JSMN_UNDEFINED:
+ default:
+ json_type = "undefined, size=";
+ break;
+ }
+
+ getTokenContent(json_value, &tokenArray_[i]);
+ fprintf(stderr, "%06d: type=%s%04d, value=%s\n", i+1, json_type, tokenArray_[i].size, json_value.c_str());
+ }
+ fprintf(stderr, "=============================== END JSON DUMP ===============================\n");
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::parseJSON()
+{
+ if ((NULL == tokenArray_) || (tokenNumber_ < 1))
+ return EC_IllegalCall;
+
+ OFJsmnParser jsmnParser;
+ jsmn_init(&jsmnParser);
+
+ int parsRes = jsmn_parse(&jsmnParser, jsonDataset_, jsonDatasetLen_, tokenArray_, tokenNumber_);
+
+ if (parsRes < 0)
+ {
+ // a parse error in jsmn_parse occurred
+ DCMDATA_ERROR("parse error in JSON file");
+ if (parsRes == JSMN_ERROR_INVAL)
+ return EC_InvalidCharacter;
+ else return EC_InvalidJSONContent;
+ }
+
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::storeInlineBinaryValue(
+ DcmElement& element,
+ Uint8 *data,
+ size_t length)
+{
+ OFCondition result = EC_Normal;
+ if (NULL == data) length = 0;
+ DcmEVR evr = element.getVR();
+ if (evr == EVR_OW)
+ {
+ /* Base64 decoder produces little endian output data, convert to local byte order */
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Uint16));
+ result = element.putUint16Array(OFreinterpret_cast(Uint16 *, data), OFstatic_cast(Uint32, length / sizeof(Uint16)));
+ }
+ else if (evr == EVR_OF)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Float32));
+ result = element.putFloat32Array(OFreinterpret_cast(Float32 *, data), OFstatic_cast(Uint32, length / sizeof(Float32)));
+ }
+ else if (evr == EVR_OD)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Float64));
+ result = element.putFloat64Array(OFreinterpret_cast(Float64 *, data), OFstatic_cast(Uint32, length / sizeof(Float64)));
+ }
+ else if (evr == EVR_OL)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Uint32));
+ result = element.putUint32Array(OFreinterpret_cast(Uint32 *, data), OFstatic_cast(Uint32, length / sizeof(Uint32)));
+ }
+ else if (evr == EVR_OV)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Uint64));
+ result = element.putUint64Array(OFreinterpret_cast(Uint64 *, data), OFstatic_cast(Uint32, length / sizeof(Uint64)));
+ }
+ else if (evr == EVR_OB || evr == EVR_UN)
+ {
+ result = element.putUint8Array(data, OFstatic_cast(Uint32, length));
+ }
+ else
+ {
+ DCMDATA_ERROR("invalid VR Type for inline value");
+ return EC_InvalidVR;
+ }
+
+ if (result.bad())
+ {
+ DCMDATA_ERROR("failed to store inline binary value for DICOM element " << element.getTag() << ": " << result.text());
+ }
+ return result;
+}
+
+
+OFCondition DcmJSONReader::storeBulkValue(
+ DcmElement& element,
+ Uint8 *data,
+ size_t length)
+{
+ OFCondition result = EC_Normal;
+ if (NULL == data) length = 0;
+ DcmEVR evr = element.getVR();
+
+ if (evr == EVR_OB || evr == EVR_UN)
+ {
+ // sequence of bytes, no byte swapping necessary
+ result = element.putUint8Array(data, OFstatic_cast(Uint32, length));
+ }
+ else if (evr == EVR_DS || evr == EVR_IS || evr == EVR_LT || evr == EVR_ST || evr == EVR_UT || evr == EVR_UC)
+ {
+ // sequence of bytes, no byte swapping necessary
+ result = element.putString(OFreinterpret_cast(char *, data), OFstatic_cast(Uint32, length));
+ }
+ else if (evr == EVR_OW || evr == EVR_US)
+ {
+ // bulk data is always in little endian, convert to local byte order
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Uint16));
+ result = element.putUint16Array(OFreinterpret_cast(Uint16 *, data), OFstatic_cast(Uint32, length / sizeof(Uint16)));
+ }
+ else if (evr == EVR_SS)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Sint16));
+ result = element.putSint16Array(OFreinterpret_cast(Sint16 *, data), OFstatic_cast(Uint32, length / sizeof(Sint16)));
+ }
+ else if (evr == EVR_OL || evr == EVR_UL)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Uint32));
+ result = element.putUint32Array(OFreinterpret_cast(Uint32 *, data), OFstatic_cast(Uint32, length / sizeof(Uint32)));
+ }
+ else if (evr == EVR_SL)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Sint32));
+ result = element.putSint32Array(OFreinterpret_cast(Sint32 *, data), OFstatic_cast(Uint32, length / sizeof(Sint32)));
+ }
+ else if (evr == EVR_OV || evr == EVR_UV)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Uint64));
+ result = element.putUint64Array(OFreinterpret_cast(Uint64 *, data), OFstatic_cast(Uint32, length / sizeof(Uint64)));
+ }
+ else if (evr == EVR_SV)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Sint64));
+ result = element.putSint64Array(OFreinterpret_cast(Sint64 *, data), OFstatic_cast(Uint32, length / sizeof(Sint64)));
+ }
+ else if (evr == EVR_FL || evr == EVR_OF)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Float32));
+ result = element.putFloat32Array(OFreinterpret_cast(Float32 *, data), OFstatic_cast(Uint32, length / sizeof(Float32)));
+ }
+ else if (evr == EVR_FD || evr == EVR_OD)
+ {
+ swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, data, OFstatic_cast(Uint32, length), sizeof(Float64));
+ result = element.putFloat64Array(OFreinterpret_cast(Float64 *, data), OFstatic_cast(Uint32, length / sizeof(Float64)));
+ }
+ else
+ {
+ DCMDATA_ERROR("invalid VR Type for bulk data");
+ return EC_InvalidVR;
+ }
+
+ if (result.bad())
+ {
+ DCMDATA_ERROR("failed to store bulk data value for DICOM element " << element.getTag() << ": " << result.text());
+ }
+ return result;
+}
+
+
+OFCondition DcmJSONReader::processJSONEscapeCharacters(OFString& value)
+{
+ /*
+ \" represents the quotation mark character (U+0022).
+ \\ represents the reverse solidus character (U+005C).
+ \/ represents the solidus character (U+002F).
+ \b represents the backspace character (U+0008).
+ \f represents the form feed character (U+000C).
+ \n represents the line feed character (U+000A).
+ \r represents the carriage return character (U+000D).
+ \t represents the character tabulation character (U+0009).
+ */
+ OFString escapeSeq = "\"\\/bfnrt";
+
+ // find backslash
+ for (size_t backSlash = value.find('\\');
+ backSlash < value.length();
+ backSlash = value.find('\\', backSlash + 1))
+ {
+ if (value.length() < backSlash + 2)
+ {
+ // the given string is shorter than expected. just return the string
+ DCMDATA_ERROR("incomplete JSON escape sequence");
+ return EC_InvalidJSONContent;
+ }
+ char sigChar = value[backSlash + 1];
+ OFString front = value.substr(0, backSlash);
+ OFString escString, back, replacement;
+ unsigned int unicodeCodepoint = 0;
+
+ if (escapeSeq.find(sigChar) < escapeSeq.length())
+ {
+ back = value.substr(backSlash + 2);
+ escString = sigChar;
+
+ switch (sigChar)
+ {
+ case 'b':
+ unicodeCodepoint = 0x0008;
+ replacement = OFstatic_cast(char, unicodeCodepoint);
+ break;
+ case 'f':
+ unicodeCodepoint = 0x000C;
+ replacement = OFstatic_cast(char, unicodeCodepoint);
+ break;
+ case 'n':
+ unicodeCodepoint = 0x000A;
+ replacement = OFstatic_cast(char, unicodeCodepoint);
+ break;
+ case 'r':
+ unicodeCodepoint = 0x000D;
+ replacement = OFstatic_cast(char, unicodeCodepoint);
+ break;
+ case 't':
+ unicodeCodepoint = 0x0009;
+ replacement = OFstatic_cast(char, unicodeCodepoint);
+ break;
+ default: // \ / "
+ replacement = sigChar;
+ break;
+ }
+ }
+ else
+ {
+ // does not contain the full pattern of "\uXXXX"
+ if (sigChar != 'u' || value.length() < backSlash + 6)
+ {
+ // unknown escape sequence or incomplete unicode code point
+ DCMDATA_ERROR("unknown JSON escape sequence or incomplete Unicode code point");
+ return EC_InvalidJSONContent;
+ }
+
+ escString = value.substr(backSlash + 2, 4);
+ // parse escString to unicodeCodepoint
+ if (sscanf(escString.c_str(), "%x", &unicodeCodepoint) != 1)
+ {
+ // Invalid hex code
+ DCMDATA_ERROR("invalid hex code in JSON escape sequence");
+ return EC_InvalidJSONContent;
+ }
+
+ // convert Unicode codepoint to UTF-8 string
+ if (unicodeCodepoint < 0x80)
+ {
+ // UTF-8 sequence with one byte
+ replacement = OFstatic_cast(char, unicodeCodepoint);
+ back = value.substr(backSlash + 6);
+ }
+ else if (unicodeCodepoint < 0x800)
+ {
+ // UTF-8 sequence with two bytes
+ replacement = OFstatic_cast(char, ((unicodeCodepoint >> 6) & 0x1F) | 0xC0);
+ replacement += OFstatic_cast(char, ((unicodeCodepoint >> 0) & 0x3F) | 0x80);
+ back = value.substr(backSlash + 6);
+ }
+ else if ((unicodeCodepoint >= 0xD800) && ((unicodeCodepoint < 0xE000)))
+ {
+ // UTF-16 surrogate pair consisting two Unicode code points
+ if ((value.length() < backSlash + 12) || (value[backSlash + 6] != '\\') || (value[backSlash + 7] != 'u'))
+ {
+ DCMDATA_ERROR("invalid JSON UTF-16 surrogate pair escape sequence");
+ return EC_InvalidJSONContent;
+ }
+
+ escString = value.substr(backSlash + 8, 4);
+ unsigned int unicodeCodepoint2;
+ if (sscanf(escString.c_str(), "%x", &unicodeCodepoint2) != 1)
+ {
+ // Invalid hex code
+ DCMDATA_ERROR("invalid hex code in JSON escape sequence");
+ return EC_InvalidJSONContent;
+ }
+
+ // combine the two UTF-16 surrogates to a single Unicode code point.
+ // The first code point is the high surrogate (D800..DBFF), the second one the low surrogate (DC00..DFFF)
+ unicodeCodepoint = ((unicodeCodepoint - 0xD800) << 10) + unicodeCodepoint2 - 0xDC00 + 0x10000;
+ // UTF-8 sequence with four bytes
+ replacement = OFstatic_cast(char, ((unicodeCodepoint >> 18) & 0x07) | 0xF0);
+ replacement += OFstatic_cast(char, ((unicodeCodepoint >> 12) & 0x3F) | 0x80);
+ replacement += OFstatic_cast(char, ((unicodeCodepoint >> 6) & 0x3F) | 0x80);
+ replacement += OFstatic_cast(char, ((unicodeCodepoint >> 0) & 0x3F) | 0x80);
+ back = value.substr(backSlash + 12);
+ }
+ else
+ {
+ // UTF-8 sequence with three bytes
+ replacement = OFstatic_cast(char, ((unicodeCodepoint >> 12) & 0x0F) | 0xE0);
+ replacement += OFstatic_cast(char, ((unicodeCodepoint >> 6) & 0x3F) | 0x80);
+ replacement += OFstatic_cast(char, ((unicodeCodepoint >> 0) & 0x3F) | 0x80);
+ back = value.substr(backSlash + 6);
+ }
+ }
+ DCMDATA_TRACE("the escaped string [" << escString << "] is parsed to UTF-8:"
+ << replacement << " - unicode:" << std::hex << unicodeCodepoint);
+ value = front + replacement + back;
+ }
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::parseElement(
+ DcmItem* dataset,
+ DcmItem* metaheader,
+ OFJsmnTokenPtr& current)
+{
+ OFCondition result = EC_Normal;
+ DCMDATA_TRACE("element at " << current->start);
+
+ // the key for the element tag has to be a string
+ if (current->type != JSMN_STRING)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: element tag must be a JSON string");
+ return EC_InvalidJSONType;
+ }
+
+ DcmTagKey tagkey;
+ result = extractTag(current, tagkey);
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+ DcmTag dcmTag(tagkey);
+
+ // the next token contains the whole element encapsulated into a JSON object.
+ current++;
+ if (current->type != JSMN_OBJECT)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: element content must be a JSON object");
+ return EC_InvalidJSONType;
+ }
+
+ // number of attributes for the element
+ int contentSize = current->size;
+ DcmElement* newElem = NULL;
+ current++;
+
+ // examine the attributes
+ OFJsmnTokenPtr vrToken = NULL, valueToken = NULL;
+ OFString valueType;
+ for (int count = 0; count < contentSize; count++)
+ {
+ OFString attrName;
+ getTokenContent(attrName, current);
+ attrName = OFStandard::toLower(attrName);
+ DCMDATA_TRACE("attribute '" << attrName << "' token at " << current->start << " - " << current->end);
+ current++;
+
+ if (attrName == "vr")
+ {
+ if (vrToken == NULL)
+ vrToken = current;
+ else
+ DCMDATA_WARN("attribute '" << attrName << " already present in this JSON object. This token will be ignored");
+ }
+ else
+ {
+ if (attrName == "bulkdatauri" || attrName == "inlinebinary" || attrName == "value")
+ {
+ if (valueToken == NULL)
+ {
+ valueToken = current;
+ valueType = attrName;
+ }
+ else
+ DCMDATA_WARN("attribute '" << attrName << " already present in this JSON object. This token will be ignored");
+ }
+ else
+ {
+ DCMDATA_ERROR("unknown JSON attribute name \"" << attrName << "\"");
+ return EC_InvalidJSONContent;
+ }
+ }
+ // find the next token in the current hierarchie
+ OFJsmnTokenPtr tmpToken = current;
+ while (current->start < tmpToken->end)
+ current++;
+ }
+
+ OFString vr = "";
+ if (vrToken != NULL)
+ getTokenContent(vr, vrToken);
+
+ // create DICOM element
+ result = createElement(newElem, dcmTag, vr);
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+
+ if (valueToken == NULL)
+ {
+ // no content following, element value remains empty
+ DCMDATA_TRACE("no value token for element " << dcmTag << ", using empty value");
+ }
+
+ // bulk data URIs reference a file, download URL or a URN referencing another MIME part in multipart/related structure.
+ // This is not yet supported
+ else if (valueType == "bulkdatauri")
+ {
+ if (ignoreBulkdataURIPolicy_)
+ {
+ // leave the element with BulkdataURI empty
+ DCMDATA_INFO("ignoring BulkdataURI for element: " << dcmTag << ", leaving element empty");
+ }
+ else
+ {
+ // the URI value has to be a JSON string
+ if (valueToken->type != JSMN_STRING)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: BulkdataURI value must be a JSON string");
+ delete newElem;
+ return EC_InvalidJSONType;
+ }
+
+ OFString value;
+ getTokenContent(value, valueToken);
+
+ if (isFileURI(value))
+ {
+ // convert URI to file path
+ OFString filePath;
+ OFString filePathNormalized;
+ size_t offset = 0;
+ size_t length = 0;
+ result = fileURItoPath(value, filePath, offset, length);
+ if (result.bad())
+ {
+ delete newElem;
+ return result;
+ }
+
+ // normalize file path
+ result = normalizePath(filePath, filePathNormalized);
+ if (result.bad())
+ {
+ delete newElem;
+ return result;
+ }
+
+ // check if file path is present in our list of permitted paths
+ if (! bulkdataPathPermitted(filePathNormalized))
+ {
+ DCMDATA_ERROR("BulkdataURI refers to a directory that is not permitted for bulk data: '" << filePath << "'");
+ delete newElem;
+ return EC_InvalidFilename;
+ }
+
+ // read the file content and insert it into the current element
+ result = loadBulkdataFile(*newElem, filePathNormalized, offset, length);
+ if (result.bad())
+ {
+ delete newElem;
+ return result;
+ }
+ }
+ else if (isHttpURI(value))
+ {
+ DCMDATA_ERROR("loading Bulkdata from http/https BulkDataURI not yet possible");
+ delete newElem;
+ return EC_UnsupportedURIType;
+ }
+ else
+ {
+ DCMDATA_ERROR("Unsupported BulkDataURI URI type: '" << value << "'");
+ delete newElem;
+ return EC_UnsupportedURIType;
+ }
+ }
+ }
+
+ // inlinebinary - content is base64 encoded
+ else if (valueType == "inlinebinary")
+ {
+ // the base64 value has to be a JSON string
+ if (valueToken->type != JSMN_STRING)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: InlineBinary value must be a JSON string");
+ delete newElem;
+ return EC_InvalidJSONType;
+ }
+
+ OFString value;
+ getTokenContent(value, valueToken);
+ Uint8* data = NULL;
+ const size_t length = OFStandard::decodeBase64(value, data);
+ DCMDATA_TRACE("parsing inline binary (" << length << "): " << value << " | " << data);
+ if (length > 0)
+ result = storeInlineBinaryValue(*newElem, data, length);
+
+ /* delete buffer since data is copied into the element */
+ delete[] data;
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+ }
+ else if (valueType == "value")
+ {
+ if (valueToken->type != JSMN_ARRAY)
+ {
+ // the value of the element has to be an array
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: attribute value must be a JSON array");
+ delete newElem;
+ return EC_InvalidJSONType;
+ }
+
+ // Sequence
+ if (newElem->ident() == EVR_SQ)
+ {
+ result = parseSequence(*(OFstatic_cast(DcmSequenceOfItems*, newElem)), valueToken);
+ }
+ else if (newElem->getTag() == DCM_PixelData)
+ {
+ // special handling for pixel data
+ DCMDATA_ERROR("pixel data must not have a 'value' attribute in the DICOM JSON model");
+ delete newElem;
+ return EC_InvalidJSONContent;
+ }
+ else
+ {
+ // parse the value array
+ DCMDATA_TRACE("parsing value array of size " << valueToken->size);
+ result = parseElementValueArray(newElem, valueToken);
+ }
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+ }
+ else
+ {
+ DCMDATA_ERROR("unknown JSON attribute name: " << valueType);
+ delete newElem;
+ return EC_InvalidJSONContent;
+ }
+
+ if (result.good())
+ {
+ // insert the new attribute to the metaheader if the tag is (0002,xxxx), otherwise to the dataset
+ if (dcmTag.getGroup() == 0x0002)
+ {
+ if (ignoreMetaInfoPolicy_ || (metaheader == NULL))
+ {
+ // we ignore meta info elements
+ delete newElem;
+ }
+ else
+ {
+ if (dcmTag.getElement() == 0x0010)
+ {
+ // this is (0002,0010) TransferSyntaxUID, extract the transfer syntax
+ OFString value;
+ newElem->getOFString(value, 0);
+ xferSyntax_ = DcmXfer(value.c_str()).getXfer();
+ }
+ result = metaheader->insert(newElem, OFFalse /*replaceOld*/);
+ }
+ }
+ else
+ {
+ result = dataset->insert(newElem, OFFalse /*replaceOld*/);
+ }
+ if (result.bad())
+ {
+ DCMDATA_WARN("element " << dcmTag << " found twice in one data set or item, ignoring second entry");
+ delete newElem;
+ }
+ }
+ else // result.bad()
+ {
+ /* delete element if insertion or putting the value failed */
+ delete newElem;
+ }
+ return result;
+}
+
+
+OFCondition DcmJSONReader::extractTag(
+ OFJsmnTokenPtr keyToken,
+ DcmTagKey& tagkey)
+{
+ OFString tagString;
+ getTokenContent(tagString, keyToken);
+ if (tagString.empty() || tagString.size() != 8)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: expected attribute tag string with 8 characters, found '" << tagString << "'");
+ return EC_InvalidTag;
+ }
+ unsigned long group, element;
+ OFString gStr = tagString.substr(0, 4);
+ OFString eStr = tagString.substr(4);
+ if (sscanf(gStr.c_str(), "%lx", &group) != 1
+ || sscanf(eStr.c_str(), "%lx", &element) != 1)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: attribute tag must consist of two 16-bit hex numbers");
+ return EC_InvalidTag;
+ }
+
+ tagkey.set(OFstatic_cast(Uint16, group), OFstatic_cast(Uint16, element));
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::parseSequence(
+ DcmSequenceOfItems& sequence,
+ OFJsmnTokenPtr& current)
+{
+ OFCondition result = EC_Normal;
+ int sqSize = current->size;
+ int sqStart = current->start;
+
+ DCMDATA_TRACE("sequence start: " << sqStart << " with size: " << sqSize);
+ current++;
+
+ // iterate over sequence items
+ for (int i = 0; i < sqSize; i++)
+ {
+ DCMDATA_TRACE("item " << sqStart << ":" << i << " -- " << current->start);
+
+ // sequence items have to be an object
+ if (current->type != JSMN_OBJECT)
+ return EC_InvalidJSONType;
+
+ // create new sequence item
+ DcmItem* newItem = new DcmItem();
+ if (newItem != NULL)
+ {
+ sequence.insert(newItem);
+
+ // proceed parsing the item content
+ result = parseDataSet(newItem, NULL, current);
+ if (result.bad() && stopOnErrorPolicy_) return result;
+ }
+ DCMDATA_TRACE("item " << sqStart << ":" << i << " end, next up : " << current->start);
+ }
+ DCMDATA_TRACE("sequence end: " << sqStart << "; next element: " << current->start);
+ return result;
+}
+
+
+OFCondition DcmJSONReader::parseDataSet(
+ DcmItem* dataset,
+ DcmItem* metaheader,
+ OFJsmnTokenPtr& current)
+{
+ OFCondition result = EC_Normal;
+
+ // we expext a JSON object that encapsulates the DICOM dataset
+ if (current->type != JSMN_OBJECT)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: datasets must be encapsulated in a JSON object");
+ return EC_InvalidJSONType;
+ }
+ int dsSize = current->size;
+ int dsStart = current->start;
+
+ DCMDATA_TRACE("dataset start " << dsStart << " - size: " << dsSize);
+ current++;
+ for (int i = 0; i < dsSize; i++)
+ {
+ // read each entry in the content object as a DICOM element
+ result = parseElement(dataset, metaheader, current);
+ if (result.bad() && stopOnErrorPolicy_) return result;
+ }
+ DCMDATA_TRACE("dataset end " << dsStart << "; next element: " << current->start);
+ return result;
+}
+
+
+
+
+OFCondition DcmJSONReader::parsePersonName(
+ OFString& value,
+ OFJsmnTokenPtr& current)
+{
+ static const char *PersonGroupNames[] = { "Alphabetic", "Ideographic", "Phonetic" };
+
+ OFCondition result;
+ int size = current->size;
+ if (size > 3)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: a person name must have at most three component groups");
+ return EC_InvalidJSONType;
+ }
+
+ OFVector<OFString> pn(3);
+ for (int i = 0; i < size; i++)
+ {
+ current++;
+ if (current->type != JSMN_STRING)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: PN values must be JSON strings");
+ return EC_InvalidJSONType;
+ }
+
+ OFString key;
+ getTokenContent(key, current);
+ int idx = -1;
+ for (int j = 0; j < 3; j++)
+ {
+ if (key == PersonGroupNames[j])
+ {
+ idx = j;
+ break;
+ }
+ }
+ if (idx < 0)
+ {
+
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: unsupported PN component group type '" << key << "'");
+ return EC_InvalidJSONType;
+ }
+
+ // if pn[idx] is not empty, it will be overwritten.
+ current++;
+ if (current->type != JSMN_STRING)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: PN values must be JSON strings");
+ return EC_InvalidJSONType;
+ }
+
+ getTokenContent(pn[idx], current);
+
+ DCMDATA_TRACE("person name (PN) with " << key << " val " << pn[idx]);
+ result = processJSONEscapeCharacters(pn[idx]);
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+ }
+
+ // PN format is: "alphPN=ideoPN=phonPN"
+ if (!pn[0].empty())
+ value += pn[0];
+ if (!pn[1].empty() || !pn[2].empty())
+ value += '=' + pn[1];
+ if (!pn[2].empty())
+ value += '=' + pn[2];
+ DCMDATA_TRACE("PN value " << value);
+ return result;
+}
+
+
+OFCondition DcmJSONReader::parseElementValueArray(
+ DcmElement*& newElem,
+ OFJsmnTokenPtr& current)
+{
+ OFCondition result;
+ OFString vmString;
+ OFString value;
+ int vm = current->size;
+
+ for (int count = 0; count < vm; count++)
+ {
+ value.clear();
+ current++;
+ if (newElem->ident() == EVR_PN)
+ {
+ // special handling for person names (PN)
+ OFString tokenValue;
+ getTokenContent(tokenValue, current);
+ DCMDATA_TRACE("element value array, parsing PN value: " << tokenValue);
+ if (current->type != JSMN_OBJECT)
+ {
+ if (tokenValue == "null")
+ {
+ value = "";
+ }
+ else
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: PN components must be JSON strings or null");
+ return EC_InvalidJSONType;
+ }
+ }
+ else
+ {
+ result = parsePersonName(value, current);
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+ }
+ if (count > 0)
+ vmString += '\\';
+ vmString += value;
+ }
+ else if (newElem->ident() == EVR_AT)
+ {
+ // special handling for attribute tags (AT).
+ // DcmAttributeTag::putOFStringArray() expects a format like this: "(0008,0020)\(0008,0030)"
+ if (current->type != JSMN_STRING)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: AT values must be JSON strings");
+ return EC_InvalidJSONType;
+ }
+
+ DcmTagKey tagkey;
+ result = extractTag(current, tagkey);
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+ DCMDATA_TRACE("element value array, parsing AT value: " << tagkey.toString());
+
+ if (count > 0)
+ vmString += '\\';
+ vmString += tagkey.toString();
+ }
+ else
+ {
+ // default for all other VRs (numeric and text)
+ if (current->type != JSMN_PRIMITIVE && current->type != JSMN_STRING)
+ {
+ DCMDATA_ERROR("not a valid DICOM JSON dataset: expected number, string or null");
+ return EC_InvalidJSONType;
+ }
+
+ getTokenContent(value, current);
+ if (current->type == JSMN_STRING)
+ {
+ // JSMN_STRING
+ DCMDATA_TRACE("element value array, parsing string value: " << value);
+ result = processJSONEscapeCharacters(value);
+ if (result.bad())
+ {
+ if (stopOnErrorPolicy_) return result; else result = EC_Normal;
+ }
+ }
+ else
+ {
+ // JSMN_PRIMITIVE, i.e. null, number, or boolean (which should not occur)
+ // Replace "null" by an empty string and keep numbers as they are
+ if (value == "null") value = "";
+ }
+ if (count > 0)
+ vmString += '\\';
+ vmString += value;
+ DCMDATA_TRACE("element value array: all values: " << vmString);
+ }
+ }
+
+ result = newElem->putOFStringArray(vmString);
+ if (result.bad())
+ {
+ DCMDATA_ERROR("failed to store string value for element " << newElem->getTag() << ": " << result.text());
+ }
+ return result;
+}
+
+
+
+
+OFCondition DcmJSONReader::createElement(
+ DcmElement*& newElem,
+ DcmTag& dcmTag,
+ const OFString& vr)
+{
+ OFCondition result = EC_Normal;
+
+ DCMDATA_TRACE("parsing VR: " << vr);
+
+ // convert vr string
+ const DcmVR jsonVR(vr.c_str());
+ if (jsonVR.isUnknown() || jsonVR.isInvalid())
+ {
+ // check whether "vr" attribute exists
+ if (vr.empty() || vr == "")
+ {
+ DCMDATA_WARN("missing 'vr' attribute for " << dcmTag
+ << ", using the tag's VR (" << dcmTag.getVR().getVRName() << ")");
+ }
+ else {
+ DCMDATA_WARN("invalid 'vr' attribute (" << vr << ") for " << dcmTag
+ << ", using the tag's VR (" << dcmTag.getVR().getVRName() << ")");
+ }
+ }
+ else
+ {
+ const DcmEVR dcmEVR = jsonVR.getEVR();
+ const DcmEVR dictionaryEVR = dcmTag.getEVR();
+
+ // Check if the VR is correct and print a warning otherwise.
+ //
+ // Normally, the JSON file and the data dictionary should specify the same
+ // VR for a tag (i.e., dictionaryEVR == dcmEVR), or dictionaryEVR is EVR_UNKNOWN
+ // if the tag is not present in our data dictionary.
+
+ if ((dictionaryEVR != dcmEVR) && (dictionaryEVR != EVR_UNKNOWN) &&
+ // LUTData VR can be US, SS or OW
+ ((dcmTag.getTagKey() != DCM_LUTData) || ((dcmEVR != EVR_US) && (dcmEVR != EVR_SS) && (dcmEVR != EVR_OW))) &&
+ // If the dictionary says "EVR_xs", the VR can either be US or SS
+ ((dictionaryEVR != EVR_xs) || ((dcmEVR != EVR_US) && (dcmEVR != EVR_SS))) &&
+ // If the dictionary says "EVR_ox" (OB/OW) or "EVR_px" (pixel data), the VR can either be OB or OW
+ (((dictionaryEVR != EVR_ox) && (dictionaryEVR != EVR_px)) || ((dcmEVR != EVR_OB) && (dcmEVR != EVR_OW))))
+ {
+ // there are inconsistencies concerning the VR in the JSON file.
+ // print a warning since there may be resulting errors in the DICOM dataset
+ DCMDATA_WARN("element " << dcmTag << " has wrong VR (" << jsonVR.getVRName()
+ << "), correct is '" << dcmTag.getVR().getVRName() << "'");
+ }
+
+ // change the VR to the one specified in the JSON dataset, even if it does not match our dictionary
+ dcmTag.setVR(jsonVR);
+ }
+
+ // create DICOM element with given tag and VR
+ result = DcmItem::newDicomElementWithVR(newElem, dcmTag);
+ if (result.bad())
+ {
+ DCMDATA_ERROR("failed to create DICOM element " << dcmTag << ": " << result.text());
+ }
+
+ // if this is pixel data, create an empty unencapsulated representation
+ // to make sure that writing the element with empty value will not fail
+ if (dcmTag == DCM_PixelData) newElem->putUint16Array(NULL,0);
+ return result;
+}
+
+
+OFCondition DcmJSONReader::readAndConvertJSONFile(
+ DcmFileFormat& fileformat,
+ const char *ifname)
+{
+ // clear old buffers, in case this object is re-used
+ clear();
+ DcmMetaInfo* metaheader = fileformat.getMetaInfo();
+ DcmDataset* dataset = fileformat.getDataset();
+ OFCondition result;
+
+ // readin the input file to a memory buffer
+ OFString stdinName("-");
+ if (ifname == stdinName)
+ result = readJSONFromStdin();
+ else result = readJSONFile(ifname);
+ if (result.bad()) return result;
+
+ // calculate tokens needed for the parser and allocate tokens
+ result = reserveTokens();
+ if (result.bad()) return result;
+
+ // use the JSON library to parse the string and save it to the token array.
+ result = parseJSON();
+ if (result.bad() && stopOnErrorPolicy_) return result;
+
+ // check if the token array starts with a JSON array or a JSON object
+ OFJsmnTokenPtr current = tokenArray_;
+ if (current->type == JSMN_ARRAY)
+ {
+ if (current->size < 1)
+ {
+ DCMDATA_ERROR("found empty JSON array instead of DICOM JSON dataset");
+ return EC_InvalidJSONContent;
+ }
+ if (current->size == 1)
+ {
+ // this is a JSON array containing a single DICOM dataset.
+ // Silently ignore the array structure and parse the dataset
+ DCMDATA_DEBUG("parsing JSON array containing a single dataset");
+ current++;
+ result = parseDataSet(dataset, metaheader, current);
+ }
+ else
+ {
+ // this is a JSON array containing a multiple DICOM datasets.
+ if (arrayHandlingPolicy_ < 0)
+ {
+ // reject multiple datasets
+ DCMDATA_ERROR("found JSON array containing " << current->size << " DICOM datasets, rejecting conversion");
+ result = EC_InvalidJSONContent;
+ }
+ else if (arrayHandlingPolicy_ == 0)
+ {
+ // Store multiple datasets in a private sequence.
+ DCMDATA_DEBUG("parsing JSON array containing " << current->size << " DICOM datasets");
+ DcmTag private_reservation(0x0009,0x0010, EVR_LO);
+ DcmTag private_sequence(0x0009,0x1000, EVR_SQ);
+ DcmSequenceOfItems *newSQ = new DcmSequenceOfItems(private_sequence);
+ result = dataset->putAndInsertString(private_reservation, JSON2DCM_PRIVATE_RESERVATION);
+ if (result.good()) result = dataset->insert(newSQ);
+ if (result.good()) result = parseSequence(*newSQ, current);
+ }
+ else
+ {
+ // select a single dataset from the array
+ if (arrayHandlingPolicy_ > current->size)
+ {
+ DCMDATA_ERROR("found JSON array containing " << current->size << " DICOM datasets, cannot store dataset no. " << arrayHandlingPolicy_);
+ result = EC_InvalidJSONContent;
+ }
+ else
+ {
+ DCMDATA_DEBUG("selecting dataset " << arrayHandlingPolicy_ << " from JSON array containing " << current->size << " DICOM datasets");
+
+ // move "current" to the token representing the first dataset
+ current++;
+
+ // number of datasets to skip
+ signed long tokensToSkip = arrayHandlingPolicy_ - 1;
+
+ // recursively skip tokens including their sub-tokens until we are done
+ while (tokensToSkip > 0)
+ {
+ tokensToSkip += current->size;
+ current++;
+ tokensToSkip--;
+ }
+
+ // extract the single dataset at the target location
+ result = parseDataSet(dataset, metaheader, current);
+ }
+ }
+ }
+ }
+ else
+ {
+ // we expect a single dataset here, parseDataSet() will check if it is the right JSON structure
+ DCMDATA_DEBUG("parsing single JSON dataset");
+ result = parseDataSet(dataset, metaheader, current);
+ }
+
+ if (!stopOnErrorPolicy_) result = EC_Normal;
+ return result;
+}
+
+
+OFBool DcmJSONReader::isFileURI(const OFString& uri) const
+{
+ return (uri.substr(0, 6) == "file:/");
+}
+
+
+OFBool DcmJSONReader::isHttpURI(const OFString& uri) const
+{
+ OFString s = uri.substr(0, 8);
+ if (s == "https://") return OFTrue;
+ s.erase(7);
+ return (s == "http://");
+}
+
+
+OFCondition DcmJSONReader::urlDecode(OFString& uri) const
+{
+ size_t pos;
+ unsigned int val = 0;
+ char c;
+ while (OFString_npos != (pos = uri.find("%")))
+ {
+ if (uri.length() + 3 < pos)
+ {
+ DCMDATA_ERROR("incomplete URL code: " << uri.substr(pos, 3));
+ return EC_UnsupportedURIType;
+
+ }
+ c = uri[pos+1];
+ if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')))
+ {
+ DCMDATA_ERROR("invalid URL code: " << uri.substr(pos, 3));
+ return EC_UnsupportedURIType;
+ }
+
+ c = uri[pos+2];
+ if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')))
+ {
+ DCMDATA_ERROR("invalid URL code: " << uri.substr(pos, 3));
+ return EC_UnsupportedURIType;
+ }
+
+ if (1 != sscanf(uri.c_str() + pos, "%%%2x", &val))
+ {
+ DCMDATA_ERROR("invalid URL code: " << uri.substr(pos, 3));
+ return EC_UnsupportedURIType;
+ }
+ uri[pos] = OFstatic_cast(char, val);
+ uri.erase(pos+1, 2);
+ }
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::fileURItoPath(const OFString& uri, OFString& filepath, size_t& offset, size_t& length) const
+{
+ // clear output parameters
+ filepath.clear();
+ offset = 0;
+ length = 0;
+
+ // check if this is a file URI at all
+ if ((uri.substr(0, 6) != "file:/") || (uri.length() < 7))
+ {
+ DCMDATA_ERROR("not a file URI: " << uri);
+ return EC_UnsupportedURIType;
+ }
+
+ OFString filePath;
+ OFString params;
+
+ // check if we have URI parameters. If they are present, store them in a separate string.
+ // In any case, remove the "file:" prefix from the path.
+ size_t paramStart = uri.find("?");
+ if (paramStart == OFString_npos)
+ {
+ filePath = uri.substr(5);
+ }
+ else
+ {
+ params = uri.substr(paramStart+1);
+ filePath = uri.substr(5, paramStart-5);
+ }
+
+ OFCondition result = urlDecode(params);
+ if (result.bad()) return result;
+
+ result = urlDecode(filePath);
+ if (result.bad()) return result;
+
+ // check if we have a URI of type "file:/path" or "file://host/path"
+ if (filePath[1] == '/') // we have checked earlier that the URI is long enough for this
+ {
+ // URI type: file://host/path
+ if (filePath.substr(1, 3) == "///")
+ {
+ DCMDATA_ERROR("Access to file URIs for network hosts not supported: " << uri);
+ return EC_UnsupportedURIType;
+ }
+
+ // determine length of hostname
+ size_t separator = filePath.find('/', 2);
+ if (separator == OFString_npos)
+ {
+ DCMDATA_ERROR("file URI without path not supported: " << uri);
+ return EC_UnsupportedURIType;
+ }
+
+ // separate hostname and path
+ OFString host = filePath.substr(2, separator-2);
+ filePath = filePath.substr(separator);
+ if ((host != "") && (host != "localhost") && (host != "127.0.0.1") && (host != "ip6-localhost") && (host != "::1"))
+ {
+ DCMDATA_ERROR("Access to file URIs for network hosts not supported: " << uri);
+ return EC_UnsupportedURIType;
+ }
+ }
+ if (filePath.length() < 2)
+ {
+ DCMDATA_ERROR("file URI without path not supported: " << uri);
+ return EC_UnsupportedURIType;
+ }
+
+#ifdef HAVE_WINDOWS_H
+ if ((filePath.length() > 2) && (filePath[2] == ':'))
+ {
+ // first component of the path is a drive name. Remove leading slash.
+ // We don't do this on Posix systems because the colon character is permitted there as a filename component.
+ filePath.erase(0,1);
+ }
+#endif
+
+ // replace '/' in the path by the system specific path separator
+ size_t l = filePath.size();
+ for (size_t i = 0; i < l; ++i)
+ {
+ if (filePath[i] == '/') filePath[i] = PATH_SEPARATOR;
+ }
+
+ // now for the URI parameters...
+ size_t paramSep;
+ OFString currentParam;
+ while (params.length() > 0)
+ {
+ // separate the next parameter
+ paramSep = params.find("&");
+ if (paramSep == OFString_npos)
+ {
+ currentParam = params;
+ params = "";
+ }
+ else
+ {
+ currentParam = params.substr(0, paramSep);
+ params = params.substr(paramSep + 1);
+ }
+ if (currentParam.substr(0,7) == "offset=")
+ {
+ // convert offset
+ unsigned long ll = 0;
+ currentParam.erase(0,7);
+ if ((OFString_npos != currentParam.find_first_not_of("0123456789")) || (1 != sscanf(currentParam.c_str(), "%lu", &ll)))
+ {
+ DCMDATA_ERROR("Invalid value for URI parameter 'offset': " << currentParam);
+ return EC_UnsupportedURIType;
+ }
+ offset = OFstatic_cast(size_t, ll);
+ }
+ else if (currentParam.substr(0,7) == "length=")
+ {
+ // convert length
+ unsigned long ll = 0;
+ currentParam.erase(0,7);
+ if ((OFString_npos != currentParam.find_first_not_of("0123456789")) || (1 != sscanf(currentParam.c_str(), "%lu", &ll)))
+ {
+ DCMDATA_ERROR("Invalid value for URI parameter 'length': " << currentParam);
+ return EC_UnsupportedURIType;
+ }
+ length = OFstatic_cast(size_t, ll);
+ }
+ else
+ {
+ DCMDATA_ERROR("'file' URI with unsupported parameter '" << currentParam << "': " << uri);
+ return EC_UnsupportedURIType;
+ }
+ }
+ filepath = filePath;
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::normalizePath(const OFString& filepath_in, OFString& filepath_out) const
+{
+ filepath_out.clear();
+#ifdef HAVE_WINDOWS_H
+ char buf[32768];
+
+ // resolve a relative path to an absolute path
+ DWORD res = GetFullPathNameA(filepath_in.c_str(), 32768, buf, NULL);
+ if ((res == 0) || (res > 32768))
+ {
+ DCMDATA_ERROR("Failed to normalize file path: '" << filepath_in << "'");
+ return EC_InvalidFilename;
+ }
+
+ // resolve short file and directory name components such as "PROGRA~1"
+ // (which is the short 8.3 version for "Program Files") into the long names
+ res = GetLongPathNameA(buf, buf, 32768);
+ if ((res == 0) || (res > 32768))
+ {
+ DCMDATA_ERROR("Failed to normalize file path: '" << filepath_in << "'");
+ return EC_InvalidFilename;
+ }
+
+ // convert all characters to uppercase using a function that (hopefully)
+ // uses the same mapping table as the WIN32 file API
+ size_t len = strlen(buf);
+ if (len != CharUpperBuffA(buf, OFstatic_cast(DWORD, len)))
+ {
+ DCMDATA_ERROR("Failed to normalize file path: '" << filepath_in << "'");
+ return EC_InvalidFilename;
+ }
+ filepath_out = buf;
+#else
+ // resolve a relative path to an absolute path without symbolic links
+ char *resolved_path = realpath(filepath_in.c_str(), NULL);
+ if (resolved_path == NULL)
+ {
+ DCMDATA_ERROR("Failed to normalize file path: '" << filepath_in << "'");
+ return EC_InvalidFilename;
+ }
+ filepath_out = resolved_path;
+ free(resolved_path);
+#endif
+ return EC_Normal;
+}
+
+
+OFCondition DcmJSONReader::addPermittedBulkdataPath(const OFString& dirpath)
+{
+ OFString std_dirpath;
+ OFCondition result = normalizePath(dirpath, std_dirpath);
+ if ((std_dirpath.length() > 0) && (std_dirpath[std_dirpath.length()-1] != PATH_SEPARATOR))
+ {
+ std_dirpath.append(1, PATH_SEPARATOR);
+ }
+
+ if (result.good()) permittedBulkdataDirs_.push_back(std_dirpath);
+ return result;
+
+}
+
+
+OFBool DcmJSONReader::bulkdataPathPermitted(const OFString& filepath) const
+{
+ OFListConstIterator(OFString) iter = permittedBulkdataDirs_.begin();
+ OFListConstIterator(OFString) last = permittedBulkdataDirs_.end();
+ while (iter != last)
+ {
+ if (filepath.substr(0, (*iter).length()) == *iter) return OFTrue;
+ ++iter;
+ }
+ return OFFalse;
+}
+
+
+OFCondition DcmJSONReader::loadBulkdataFile(
+ DcmElement& element,
+ const OFString& filepath,
+ size_t offset,
+ size_t length)
+{
+ // open file for reading
+ OFFile file;
+ if (! file.fopen(filepath, "rb"))
+ {
+ OFString s("(unknown error code)");
+ file.getLastErrorString(s);
+ return makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str());
+ }
+
+ // obtain file size and check if file is large enough
+ const size_t filelen = OFStandard::getFileSize(filepath);
+ if (0 == length) length = filelen;
+ if (offset + length > filelen)
+ {
+ DCMDATA_ERROR("bulk data file too short: '" << filepath << "', expected " << offset + length << " bytes but only found " << filelen);
+ return EC_EndOfStream;
+ }
+
+ // allocate buffer
+ Uint8 *bulkDataBuffer = new (std::nothrow) Uint8[length];
+ if (bulkDataBuffer == NULL)
+ {
+ DCMDATA_ERROR("out of memory: failed to allocate buffer for bulk data file");
+ return EC_MemoryExhausted;
+ }
+
+ // seek to the given offset within the file
+ if (offset > 0)
+ {
+ if (0 != file.fseek(offset, SEEK_SET))
+ {
+ OFString s("(unknown error code)");
+ file.getLastErrorString(s);
+ delete[] bulkDataBuffer;
+ return makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str());
+ }
+ }
+
+ // read the bulk data into the buffer
+ size_t res = file.fread(bulkDataBuffer, 1, length);
+
+ // we ignore the fclose() return code, which is safe since the file is read-only
+ file.fclose();
+
+ // check the number of bytes read
+ if (res != length)
+ {
+ OFString s("(unknown error code)");
+ file.getLastErrorString(s);
+ delete[] bulkDataBuffer;
+ return makeOFCondition(OFM_dcmdata, 18, OF_error, s.c_str());
+ }
+
+ // file was successfully read into buffer. Store the result.
+ OFCondition result = storeBulkValue(element, bulkDataBuffer, length);
+ delete[] bulkDataBuffer;
+ return result;
+}
/*
*
- * Copyright (C) 1994-2019, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/ofstream.h"
+#include "dcmtk/ofstd/oflimits.h"
#include "dcmtk/dcmdata/dclist.h"
// *****************************************
-DcmListNode::DcmListNode( DcmObject *obj )
+DcmListNode::DcmListNode(DcmObject *obj)
: nextNode(NULL),
prevNode(NULL),
objNodeValue(obj)
// *****************************************
+// value should be identical to DCM_EndOfListIndex, e.g. 0xffffffff for 32 bit
+static const unsigned long invalidListPosition = OFnumeric_limits<unsigned long>::max();
+
+
+// ********************************
+
+
DcmList::DcmList()
: firstNode(NULL),
lastNode(NULL),
currentNode(NULL),
+ currentPosition(invalidListPosition),
cardinality(0)
{
}
DcmList::~DcmList()
{
- if ( !DcmList::empty() ) // list is not empty !
+ if (!DcmList::empty())
{
- lastNode->nextNode = NULL; // set to 0 for safety reasons
+ lastNode->nextNode = NULL; // set to 0 for safety reasons
do {
DcmListNode *temp = firstNode;
firstNode = firstNode->nextNode;
- // delete temp->objNodeValue; // dangerous!
+ // delete temp->objNodeValue; // dangerous!
delete temp;
- } while ( firstNode != NULL );
+ } while (firstNode != NULL);
currentNode = firstNode = lastNode = NULL;
+ currentPosition = invalidListPosition;
}
}
// ********************************
-DcmObject *DcmList::append( DcmObject *obj )
+DcmObject *DcmList::append(DcmObject *obj)
{
- if ( obj != NULL )
+ if (obj != NULL)
{
- if ( DcmList::empty() ) // list is empty !
+ if (DcmList::empty())
+ {
currentNode = firstNode = lastNode = new DcmListNode(obj);
- else
+ currentPosition = cardinality;
+ cardinality++;
+ }
+ // check whether object can be inserted
+ else if (cardinality < DCM_EndOfListIndex)
{
DcmListNode *node = new DcmListNode(obj);
lastNode->nextNode = node;
node->prevNode = lastNode;
currentNode = lastNode = node;
+ currentPosition = cardinality;
+ cardinality++;
+ } else {
+ DCMDATA_DEBUG("DcmList::append() cannot insert object, maximum number of entries reached");
+ obj = NULL;
}
- cardinality++;
} // obj == NULL
return obj;
}
// ********************************
-DcmObject *DcmList::prepend( DcmObject *obj )
+DcmObject *DcmList::prepend(DcmObject *obj)
{
- if ( obj != NULL )
+ if (obj != NULL)
{
- if ( DcmList::empty() ) // list is empty !
+ if (DcmList::empty())
+ {
currentNode = firstNode = lastNode = new DcmListNode(obj);
- else
+ currentPosition = 0;
+ cardinality++;
+ }
+ // check whether object can be inserted
+ else if (cardinality < DCM_EndOfListIndex)
{
DcmListNode *node = new DcmListNode(obj);
node->nextNode = firstNode;
firstNode->prevNode = node;
currentNode = firstNode = node;
+ currentPosition = 0;
+ cardinality++;
+ } else {
+ DCMDATA_DEBUG("DcmList::prepend() cannot insert object, maximum number of entries reached");
+ obj = NULL;
}
- cardinality++;
} // obj == NULL
return obj;
}
// ********************************
-DcmObject *DcmList::insert( DcmObject *obj, E_ListPos pos )
+DcmObject *DcmList::insert(DcmObject *obj, const E_ListPos pos)
{
- if ( obj != NULL )
+ if (obj != NULL)
{
- if ( DcmList::empty() ) // list is empty !
+ if (DcmList::empty())
{
currentNode = firstNode = lastNode = new DcmListNode(obj);
+ currentPosition = 0;
cardinality++;
}
- else {
- if ( pos==ELP_last )
- DcmList::append( obj ); // cardinality++;
- else if ( pos==ELP_first )
- DcmList::prepend( obj ); // cardinality++;
- else if ( !DcmList::valid() )
+ // check whether object can be inserted
+ else if (cardinality < DCM_EndOfListIndex)
+ {
+ if (pos == ELP_last) // insert at the end
+ DcmList::append(obj);
+ else if (pos == ELP_first) // insert at the beginning
+ DcmList::prepend(obj);
+ else if (!DcmList::valid())
// set current node to the end if there is no predecessor or
// there are successors to be determined
- DcmList::append( obj ); // cardinality++;
- else if ( pos == ELP_prev ) // insert before current node
+ DcmList::append(obj);
+ else if (pos == ELP_prev) // insert before current node
{
DcmListNode *node = new DcmListNode(obj);
- if ( currentNode->prevNode == NULL )
- firstNode = node; // insert at the beginning
+ if (currentNode->prevNode == NULL)
+ firstNode = node; // insert at the beginning
else
currentNode->prevNode->nextNode = node;
node->prevNode = currentNode->prevNode;
node->nextNode = currentNode;
currentNode->prevNode = node;
currentNode = node;
+ // NB: no need to update currentPosition
cardinality++;
}
- else //( pos==ELP_next || pos==ELP_atpos )
- // insert after current node
+ else // (pos == ELP_next || pos == ELP_atpos)
+ // insert after current node
{
DcmListNode *node = new DcmListNode(obj);
- if ( currentNode->nextNode == NULL )
- lastNode = node; // append to the end
+ if (currentNode->nextNode == NULL)
+ lastNode = node; // append to the end
else
currentNode->nextNode->prevNode = node;
node->nextNode = currentNode->nextNode;
node->prevNode = currentNode;
currentNode->nextNode = node;
currentNode = node;
+ currentPosition++;
cardinality++;
}
+ } else {
+ DCMDATA_DEBUG("DcmList::insert() cannot insert object, maximum number of entries reached");
+ obj = NULL;
}
} // obj == NULL
return obj;
DcmObject *tempobj;
DcmListNode *tempnode;
- if ( DcmList::empty() ) // list is empty !
+ if (DcmList::empty())
return NULL;
- else if ( !DcmList::valid() )
+ else if (!DcmList::valid())
return NULL; // current node is 0
else
{
tempnode = currentNode;
- if ( currentNode->prevNode == NULL )
+ if (currentNode->prevNode == NULL)
firstNode = currentNode->nextNode; // delete first element
else
currentNode->prevNode->nextNode = currentNode->nextNode;
- if ( currentNode->nextNode == NULL )
+ if (currentNode->nextNode == NULL)
lastNode = currentNode->prevNode; // delete last element
else
currentNode->nextNode->prevNode = currentNode->prevNode;
currentNode = currentNode->nextNode;
tempobj = tempnode->value();
delete tempnode;
+ // NB: no need to update currentPosition
cardinality--;
return tempobj;
}
// ********************************
-DcmObject *DcmList::get( E_ListPos pos )
+DcmObject *DcmList::get(const E_ListPos pos)
{
- return seek( pos );
+ return seek(pos);
}
// ********************************
-DcmObject *DcmList::seek( E_ListPos pos )
+DcmObject *DcmList::seek(const E_ListPos pos)
{
switch (pos)
{
- case ELP_first :
+ case ELP_first:
currentNode = firstNode;
+ if (DcmList::valid())
+ currentPosition = 0;
+ else
+ currentPosition = invalidListPosition;
break;
- case ELP_last :
+ case ELP_last:
currentNode = lastNode;
+ if (DcmList::valid())
+ currentPosition = cardinality - 1;
+ else
+ currentPosition = invalidListPosition;
break;
- case ELP_prev :
- if ( DcmList::valid() )
+ case ELP_prev:
+ if (DcmList::valid())
+ {
currentNode = currentNode->prevNode;
+ if (DcmList::valid())
+ currentPosition--;
+ else
+ currentPosition = invalidListPosition;
+ }
break;
- case ELP_next :
- if ( DcmList::valid() )
+ case ELP_next:
+ if (DcmList::valid())
+ {
currentNode = currentNode->nextNode;
+ if (DcmList::valid())
+ currentPosition++;
+ else
+ currentPosition = invalidListPosition;
+ }
break;
default:
break;
// ********************************
-DcmObject *DcmList::seek_to(unsigned long absolute_position)
+DcmObject *DcmList::seek_to(const unsigned long absolute_position)
{
+ if (absolute_position >= cardinality)
+ {
+ // invalid position
+ currentNode = NULL;
+ currentPosition = invalidListPosition;
+ return NULL;
+ }
+ else if (absolute_position == 0)
+ {
+ // first item in the list
+ return seek(ELP_first);
+ }
+ else if (absolute_position == cardinality - 1)
+ {
+ // last item in the list
+ return seek(ELP_last);
+ }
+ else if (currentPosition != invalidListPosition)
+ {
+ // determine distance between current and requested position
+ const unsigned long distance = (absolute_position >= currentPosition)
+ ? (absolute_position - currentPosition)
+ : (currentPosition - absolute_position);
+
+ // Are we seeking to a position that is closer to the current position than to
+ // the start or end of the sequence? This is often the case, if we are using
+ // seek_to() to essentially iterate over the sequence, for example. If so, then
+ // let's start iterating from the current position. Often, the position we want
+ // is simply the next position (or maybe the previous one). Let's make those
+ // use cases be O(1), and not O(n).
+ if ((distance <= absolute_position) && (distance < cardinality - absolute_position))
+ {
+ if (currentPosition <= absolute_position)
+ {
+ while (currentPosition < absolute_position)
+ seek(ELP_next);
+ }
+ else
+ {
+ while (currentPosition > absolute_position)
+ seek(ELP_prev);
+ }
+ return get(ELP_atpos);
+ }
+ }
+
+ // iterate from the start...
if (absolute_position < cardinality / 2)
{
/* iterate over first half of the list */
- seek( ELP_first );
+ seek(ELP_first);
for (unsigned long i = 0; i < absolute_position; i++)
- seek( ELP_next );
+ seek(ELP_next);
}
- else if (absolute_position < cardinality)
+ else // ... or the end of the list
{
- /* iterate over second half of the list (starting from the end) */
- seek( ELP_last );
+ assert(absolute_position < cardinality);
+ // iterate over second half of the list (starting from the end)
+ seek(ELP_last);
for (unsigned long i = absolute_position + 1; i < cardinality; i++)
- seek( ELP_prev );
- } else {
- /* invalid position */
- currentNode = NULL;
+ seek(ELP_prev);
}
- return get( ELP_atpos );
+ return get(ELP_atpos);
}
firstNode = NULL;
lastNode = NULL;
currentNode = NULL;
+ currentPosition = invalidListPosition;
cardinality = 0;
}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
return l_error;
}
+
+// ********************************
+
+const char *DcmMetaInfo::getPreamble() const
+{
+ return filePreamble;
+}
/*
*
- * Copyright (C) 2002-2024, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofconsol.h"
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
/*
*
- * Copyright (C) 2002-2023, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofconsol.h"
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
/*
*
- * Copyright (C) 1997-2024, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// check if we have an empty uncompressed value field.
// We never encode that as BulkDataURI.
OFBool emptyValue = OFFalse;
- if ((current == repListEnd) && existUnencapsulated && (getLengthField() == 0))
+ if ((current == repListEnd) && existUnencapsulated && (getLength() == 0))
{
emptyValue = OFTrue;
}
- // now check if the pixel data will be written as
- // BulkDataURI, which is possible for both uncompressed
- // and encapsulated pixel data.
- OFString value;
- if ((! emptyValue) && format.asBulkDataURI(getTag(), value))
+ // determine the length either of the pixel sequence or of the uncompressed pixel data
+ Uint32 len = 0;
+ if (current == repListEnd) len = getLength();
+ else if ((*current)->pixSeq != NULL) len = (*current)->pixSeq->getLength();
+
+ // check if the pixel data should be written as BulkDataURI
+ if (((! emptyValue) || (current != repListEnd)) && format.asBulkDataURI(getTag(), len))
{
- /* write JSON Opener */
- writeJsonOpener(out, format);
+ // We should write the pixel data as bulk data. Now check whether
+ // we are dealing with encapsulated or unencapsulated data
+ if ((current == repListEnd) && existUnencapsulated)
+ {
+ // Current pixel data representation is unencapsulated.
+ // Write JSON Opener
+ writeJsonOpener(out, format);
- /* return defined BulkDataURI */
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
+ // adjust byte order to little endian
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
- /* write JSON Closer */
- writeJsonCloser(out, format);
- return EC_Normal;
+ // write as bulk data
+ OFCondition status = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
+
+ // write JSON Closer
+ writeJsonCloser(out, format);
+ return status;
+ }
+ else if (current != repListEnd)
+ {
+ // Current pixel data representation is encapsulated.
+ // Access the parent item to check the number of frames
+ DcmItem *parentItem = getParentItem();
+ if (parentItem == NULL)
+ {
+ // something is fishy with this dataset
+ DCMDATA_WARN("DcmPixelData: Unable to access parent dataset for pixel data object");
+ return EC_CannotWriteBulkDataFile;
+ }
+
+ // check NumberOfFrames attribute, default to 1 if absent or unreadable
+ Sint32 imageFrames = 1;
+ if (parentItem->findAndGetSint32(DCM_NumberOfFrames, imageFrames).bad()) imageFrames = 1;
+ if (imageFrames != 1)
+ {
+ DCMDATA_WARN("Encapsulated multi-frame images cannot be represented in JSON");
+ return EC_CannotWriteJSONMultiframe;
+ }
+
+ // (*current)->pixSeq is not NULL at this point, we have checked this earlier in this method
+ DcmPixelSequence *currentPixelSequence = (*current)->pixSeq;
+
+ // write JSON Opener
+ writeJsonOpener(out, format);
+
+ // delegate the JSON conversion to the pixel sequence
+ OFCondition status = currentPixelSequence->writeJson(out, format);
+
+ // write JSON Closer
+ writeJsonCloser(out, format);
+ return status;
+ }
+ else
+ {
+ // something is fishy with this dataset
+ DCMDATA_WARN("DcmPixelData: apparently there is neither compressed nor uncompressed data");
+ return EC_CannotWriteJsonInlineBinary;
+ }
}
// No bulk data URI, we're supposed to write as InlineBinary.
// pixel data is encapsulated, return error
return EC_CannotWriteJsonInlineBinary;
}
+
+
+Uint16 DcmPixelData::decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const
+{
+ if (bitsStored > bitsAllocated) return 0;
+ if (existUnencapsulated || (original == repListEnd))
+ {
+ // we have uncompressed pixel data or pixel data is empty
+ return DcmElement::decodedBitsAllocated(bitsAllocated, bitsStored);
+ }
+ else
+ {
+ return DcmCodecList::decodedBitsAllocated((*original)->repType, bitsAllocated, bitsStored);
+ }
+}
+
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofstream.h"
#include "dcmtk/ofstd/ofuuid.h"
+#include "dcmtk/ofstd/ofsha256.h"
#include "dcmtk/dcmdata/dcpixseq.h"
#include "dcmtk/dcmdata/dcpxitem.h"
#include "dcmtk/dcmdata/dcitem.h"
#include "dcmtk/dcmdata/dcvr.h"
-
#include "dcmtk/dcmdata/dcdeftag.h"
-
+#include "dcmtk/dcmdata/dcjson.h"
// ********************************
return l_error;
}
+// ********************************
+
+OFCondition DcmPixelSequence::writeJson(
+ STD_NAMESPACE ostream &out,
+ DcmJsonFormat &format)
+{
+ // At this point, we can safely assume that this is a single frame image
+ // since this has been checked in DcmPixelData::writeJson().
+
+ OFCondition status = EC_Normal;
+ unsigned long numItems = card();
+ if (numItems < 2)
+ {
+ DCMDATA_WARN("DcmPixelSequence: pixel sequence is empty");
+ return EC_CannotWriteBulkDataFile;
+ }
+
+ // compute SHA-2 checksum over all pixel data fragments,
+ // not including the basic offset table (i.e. the first item)
+ OFSHA256 sha256;
+ Uint8 hash[32];
+ DcmPixelItem *pixItem = NULL;
+ Uint8 *pixelData = NULL;
+ Uint32 fragmentLength = 0;
+ for (unsigned long i = 1; i < numItems; ++i)
+ {
+ status = getItem(pixItem, i);
+ if (status.bad()) return status;
+ fragmentLength = pixItem->getLength();
+ status = pixItem->getUint8Array(pixelData);
+ if (status.bad()) return status;
+ sha256.update(pixelData, fragmentLength);
+ }
+ sha256.final(hash);
+
+ // determine filename and path
+ DcmXfer xfer(Xfer);
+ OFString bulkname;
+ char hashstring[3];
+ for (int i=0; i < 32; ++i)
+ {
+ OFStandard::snprintf(hashstring, sizeof(hashstring), "%02x", hash[i]);
+ bulkname.append(hashstring);
+ }
+ bulkname.append(xfer.getFilenameExtension());
+
+ OFString bulkpath;
+ format.getBulkDataDirectory(bulkpath);
+ bulkpath.append(bulkname);
+
+ /* check if file already exists. In this case, the file content is the same
+ * we would create now since the SHA-256 checksum is the same. So we can just
+ * use the existing file.
+ */
+ if (! OFStandard::fileExists(bulkpath))
+ {
+ OFFile bulkfile;
+ if (! bulkfile.fopen(bulkpath.c_str(), "wb"))
+ {
+ DCMDATA_ERROR("Unable to create bulk data file '" << bulkpath << "'");
+ return EC_CannotWriteBulkDataFile;
+ }
+
+ // write all fragments into a single file, as specified in DICOM part 18, section 8.7.3.3.2.
+ for (unsigned long i = 1; i < numItems; ++i)
+ {
+ status = getItem(pixItem, i);
+ if (status.bad()) return status;
+ fragmentLength = pixItem->getLength();
+ status = pixItem->getUint8Array(pixelData);
+ if (status.bad()) return status;
+ if (fragmentLength != bulkfile.fwrite(pixelData, 1, fragmentLength))
+ {
+ DCMDATA_ERROR("Unable to write bulk data to file '" << bulkpath << "'");
+ return EC_CannotWriteBulkDataFile;
+ }
+ }
+
+ if (bulkfile.fclose())
+ {
+ DCMDATA_ERROR("Unable to close bulk data file '" << bulkpath << "'");
+ return EC_CannotWriteBulkDataFile;
+ }
+ }
+
+ // print BulkDataURI (the enclosing Json opener and closer are printed in class DcmPixelData)
+ format.printBulkDataURIPrefix(out);
+ OFString bulkDataURI;
+ format.getBulkDataURIPrefix(bulkDataURI);
+ bulkDataURI.append(bulkname);
+ DcmJsonFormat::printString(out, bulkDataURI);
+ return status;
+}
+
// ********************************
/*
*
- * Copyright (C) 2002-2024, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+Uint16 DcmRLECodecDecoder::decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 /* bitsStored */) const
+{
+ // The RLE decoder only supports images where BitsAllocated is a multiple of 8.
+ if ((bitsAllocated < 8)||(bitsAllocated % 8 != 0)) return 0;
+
+ // RLE cannot support more than 120 bits/sample (15 bands) in DICOM
+ if (bitsAllocated > 120) return 0;
+
+ return bitsAllocated;
+}
+
+
OFCondition DcmRLECodecDecoder::decode(
const DcmRepresentationParameter * /* fromRepParam */,
DcmPixelSequence * pixSeq,
{
if (rledecoder.size() < bytesPerStripe)
{
- DCMDATA_WARN("RLE decoder is finished but has produced insufficient data for this stripe, will continue with next pixel item");
+ DCMDATA_WARN("DcmRLECodecDecoder: Detected fragmented RLE compressed pixel data, which is not allowed in DICOM");
DCMDATA_DEBUG("RLE decoder processes pixel item " << currentItem);
result = pixSeq->getItem(pixItem, currentItem++);
if (result.good())
if (result.good() || result == EC_StreamNotifyClient)
{
+ DCMDATA_WARN("DcmRLECodecDecoder: Detected fragmented RLE compressed pixel data, which is not allowed in DICOM");
DCMDATA_DEBUG("RLE decoder processes pixel item " << currentItem);
result = pixSeq->getItem(pixItem, currentItem++);
}
} /* while */
// last fragment for this RLE stripe
+ if (inputBytes + byteOffset > fragmentLength)
+ {
+ DCMDATA_WARN("DcmRLECodecDecoder: Stream size in RLE header is wrong, adjusting from " << inputBytes << " to " << fragmentLength-byteOffset << " bytes");
+ inputBytes = fragmentLength-byteOffset;
+ }
+
result = rledecoder.decompress(rleData + byteOffset, OFstatic_cast(size_t, inputBytes));
// special handling for zero pad byte at the end of the RLE stream
if (lastStripeOfColor && (rledecoder.size() < bytesPerStripe))
{
// stripe ended prematurely? report a warning and continue
- DCMDATA_WARN("RLE decoder is finished but has produced insufficient data for this stripe, filling remaining pixels");
+ DCMDATA_WARN("DcmRLECodecDecoder: RLE decoder is finished but has produced insufficient data for this stripe, filling remaining pixels");
result = EC_Normal;
}
else if (rledecoder.size() != bytesPerStripe)
// if the RLE data is split in multiple fragments. We need to feed
// data fragment by fragment until the RLE codec has produced
// sufficient output.
+ if (fragmentLength < byteOffset)
+ {
+ DCMDATA_ERROR("Byte offset in RLE header is wrong.");
+ return EC_CannotChangeRepresentation;
+ }
bytesToDecode = OFstatic_cast(size_t, fragmentLength - byteOffset);
}
else
}
// adjust byte order for uncompressed image to little endian
+ if ((gLocalByteOrder == EBO_BigEndian) && (frameSize & 1))
+ {
+ DCMDATA_WARN("Size of frame buffer is odd, cannot correct byte order for last pixel value");
+ }
swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, imageData16, frameSize, sizeof(Uint16));
return result;
}
+Uint16 DcmRLECodecEncoder::decodedBitsAllocated(
+ Uint16 /* bitsAllocated */,
+ Uint16 /* bitsStored */) const
+{
+ return 0;
+}
+
+
OFCondition DcmRLECodecEncoder::decode(
const DcmRepresentationParameter * /* fromRepParam */,
DcmPixelSequence * /* pixSeq */,
/*
*
- * Copyright (C) 2011-2024, OFFIS e.V.
+ * Copyright (C) 2011-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
if (sourceVM == 0)
{
// no character set specified, use ASCII
- status = DefaultEncodingConverter.selectEncoding("ASCII", DestinationEncoding);
+ status = DefaultEncodingConverter.selectEncoding("ASCII", getDestinationEncoding());
// output some useful debug information
if (status.good())
{
DCMDATA_DEBUG("DcmSpecificCharacterSet: Selected character set '' (ASCII) "
- << "for the conversion to " << DestinationEncoding);
+ << "for the conversion to " << getDestinationEncoding());
}
}
else if (sourceVM == 1)
// check whether an appropriate character encoding has been found
if (!fromEncoding.empty())
{
- status = DefaultEncodingConverter.selectEncoding(fromEncoding, DestinationEncoding);
+ status = DefaultEncodingConverter.selectEncoding(fromEncoding, getDestinationEncoding());
// output some useful debug information
if (status.good())
{
DCMDATA_DEBUG("DcmSpecificCharacterSet: Selected character set '" << SourceCharacterSet
- << "' (" << fromEncoding << ") for the conversion to " << DestinationEncoding);
+ << "' (" << fromEncoding << ") for the conversion to " << getDestinationEncoding());
}
}
return status;
// but first check whether this encoding has already been added before
if (conv.second)
{
- status = conv.first->second.selectEncoding(encodingName, DestinationEncoding);
+ status = conv.first->second.selectEncoding(encodingName, getDestinationEncoding());
if (status.good())
{
// output some useful debug information
DCMDATA_DEBUG("DcmSpecificCharacterSet: Added character set '" << definedTerm
- << "' (" << encodingName << ") for the conversion to " << DestinationEncoding);
+ << "' (" << encodingName << ") for the conversion to " << getDestinationEncoding());
// also remember the default descriptor, which refers to the first character set
if (i == 0)
{
OFMake_pair(OFString("ISO 2022 IR 6"), OFCharacterEncoding()));
if (conv.second)
{
- status = conv.first->second.selectEncoding("ASCII", DestinationEncoding);
+ status = conv.first->second.selectEncoding("ASCII", getDestinationEncoding());
if (status.good())
{
// output some useful debug information
DCMDATA_DEBUG("DcmSpecificCharacterSet: Added character set 'ISO 2022 IR 6' (ASCII) "
- << "for the conversion to " << DestinationEncoding
+ << "for the conversion to " << getDestinationEncoding()
<< " (because it is needed for one or more of the previously added character sets)");
} else {
DCMDATA_ERROR("DcmSpecificCharacterSet: 'ISO 2022 IR 6' is not supported by"
const OFBool hasEscapeChar = checkForEscapeCharacter(fromString, fromLength);
if (EncodingConverters.empty() || (!hasEscapeChar && delimiters.empty()))
{
- if (delimiters.empty())
+ // convert string without code extensions according to ISO 2022
+ status = convertStringWithoutCodeExtensions(fromString, fromLength, toString, delimiters);
+ } else {
+ // convert string with code extensions according to ISO 2022
+ status = convertStringWithCodeExtensions(fromString, fromLength, toString, delimiters, hasEscapeChar);
+ }
+ if (status.good())
+ {
+ // finally, output some debug information
+ if (getDestinationEncoding() == "UTF-8")
{
- // no code extensions according to ISO 2022 used and no delimiters - this is the simple case
- DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
- << convertToLengthLimitedOctalString(fromString, fromLength) << "'");
- status = DefaultEncodingConverter.convertString(fromString, fromLength, toString, OFTrue /*clearMode*/);
+ // output code points only in case of UTF-8 output
+ DCMDATA_TRACE("Converted result in " << getDestinationEncoding() << " is '"
+ << convertToLengthLimitedOctalString(toString.c_str(), toString.length()) << "' ("
+ << countCharactersInUTF8String(toString) << " code points)");
} else {
- // no code extensions according to ISO 2022 used, but delimiters
- DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
- << convertToLengthLimitedOctalString(fromString, fromLength)
- << "' (with delimiters '" << delimiters << "')");
-
- toString.clear();
- size_t pos = 0;
- const char *firstChar = fromString;
- const char *currentChar = fromString;
-
- // iterate over all characters of the string (as long as there is no error)
- while ((pos < fromLength) && status.good())
- {
- const char c0 = *currentChar++;
+ DCMDATA_TRACE("Converted result in " << getDestinationEncoding() << " is '"
+ << convertToLengthLimitedOctalString(toString.c_str(), toString.length()) << "'");
+ }
+ }
+ return status;
+}
- // check for characters ESC, HT, LF, FF, CR or any other specified delimiter
- if ((c0 == '\011') || (c0 == '\012') || (c0 == '\014') || (c0 == '\015') || (delimiters.find(c0) != OFString_npos))
- {
- // convert the sub-string (before the delimiter) with the current character set
- const size_t convertLength = currentChar - firstChar - 1;
- if (convertLength > 0)
- {
- // output some debug information
- DCMDATA_TRACE(" Converting sub-string '"
- << convertToLengthLimitedOctalString(firstChar, convertLength) << "'");
- status = DefaultEncodingConverter.convertString(firstChar, convertLength, toString, OFFalse /*clearMode*/);
- if (status.bad())
- DCMDATA_TRACE(" -> ERROR: " << status.text());
- }
- // output some debug information
- DCMDATA_TRACE(" Appending delimiter '"
- << convertToLengthLimitedOctalString(currentChar - 1 /* identical to c0 */, 1)
- << "' to the output");
- // don't forget to append the delimiter
- toString += c0;
-
- // start new sub-string after delimiter
- firstChar = currentChar;
- }
- ++pos;
- }
- if (status.good())
- {
- // convert any remaining characters from the input string
- const size_t convertLength = currentChar - firstChar;
- if (convertLength > 0)
- {
- // output some debug information
- DCMDATA_TRACE(" Converting remaining sub-string '"
- << convertToLengthLimitedOctalString(firstChar, convertLength) << "'");
- status = DefaultEncodingConverter.convertString(firstChar, convertLength, toString, OFFalse /*clearMode*/);
- if (status.bad())
- DCMDATA_TRACE(" -> ERROR: " << status.text());
- }
- }
- }
+OFCondition DcmSpecificCharacterSet::convertStringWithoutCodeExtensions(const char *fromString,
+ const size_t fromLength,
+ OFString &toString,
+ const OFString &delimiters)
+{
+ OFCondition status = EC_Normal;
+ // any delimiters defined?
+ if (delimiters.empty())
+ {
+ // case 1: no code extensions used and no delimiters defined - this is the simple case
+ DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
+ << convertToLengthLimitedOctalString(fromString, fromLength) << "'");
+ status = DefaultEncodingConverter.convertString(fromString, fromLength, toString, OFTrue /*clearMode*/);
} else {
- if (delimiters.empty())
- {
- DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
- << convertToLengthLimitedOctalString(fromString, fromLength)
- << "' (with code extensions)");
- } else {
- DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
- << convertToLengthLimitedOctalString(fromString, fromLength)
- << "' (with " << (hasEscapeChar ? "code extensions and " : "")
- << "delimiters '" << delimiters << "')");
- }
- // code extensions according to ISO 2022 (possibly) used, so we need to check
- // for particular escape sequences in order to switch between character sets
+ // case 2: no code extensions used, but delimiters defined
+ DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
+ << convertToLengthLimitedOctalString(fromString, fromLength)
+ << "' (with delimiters '" << delimiters << "')");
+
toString.clear();
size_t pos = 0;
- // some (extended) character sets use more than 1 byte per character
- // (however, the default character set always uses a single byte)
- unsigned char bytesPerChar = 1;
- // check whether '=' is a delimiter, as it is used in PN values
- OFBool isFirstGroup = (delimiters.find('=') != OFString_npos);
- // by default, we expect that delimiters can be checked by their corresponding ASCII codes
- // (this implies that the default character set is not "ISO 2022 IR 87" or "ISO 2022 IR 159")
- OFBool checkDelimiters = OFTrue;
const char *firstChar = fromString;
const char *currentChar = fromString;
- // initially, use the default descriptor
- OFCharacterEncoding converter = DefaultEncodingConverter;
- DCMDATA_TRACE(" Starting with the default character set");
// iterate over all characters of the string (as long as there is no error)
while ((pos < fromLength) && status.good())
{
const char c0 = *currentChar++;
- // check for characters ESC, HT, LF, FF, CR or any other specified delimiter
- const OFBool isEscape = (c0 == '\033');
- const OFBool isDelimiter = checkDelimiters &&
- ((c0 == '\011') || (c0 == '\012') || (c0 == '\014') || (c0 == '\015') || (delimiters.find(c0) != OFString_npos));
- if (isEscape || isDelimiter)
+ // check for characters HT, LF, FF, CR or any other specified delimiter
+ const OFBool isDelimiter = ((c0 == '\011') || (c0 == '\012') || (c0 == '\014') || (c0 == '\015') ||
+ (delimiters.find(c0) != OFString_npos));
+ if (isDelimiter)
{
// convert the sub-string (before the delimiter) with the current character set
const size_t convertLength = currentChar - firstChar - 1;
// output some debug information
DCMDATA_TRACE(" Converting sub-string '"
<< convertToLengthLimitedOctalString(firstChar, convertLength) << "'");
- status = converter.convertString(firstChar, convertLength, toString, OFFalse /*clearMode*/);
+ status = DefaultEncodingConverter.convertString(firstChar, convertLength, toString, OFFalse /*clearMode*/);
if (status.bad())
DCMDATA_TRACE(" -> ERROR: " << status.text());
}
- // check whether this was the first component group of a PN value
- if (isDelimiter && (c0 == '='))
- isFirstGroup = OFFalse;
- }
- // the ESC character is used to explicitly switch between character sets
- if (isEscape)
- {
- // report a warning as this is a violation of DICOM PS 3.5 Section 6.2.1
- if (isFirstGroup)
- {
- DCMDATA_WARN("DcmSpecificCharacterSet: Escape sequences shall not be used "
- << "in the first component group of a Person Name (PN), using them anyway");
- }
- // we need at least two more characters to determine the new character set
- size_t escLength = 2;
- if (pos + escLength < fromLength)
- {
- OFString key;
- const char c1 = *currentChar++;
- const char c2 = *currentChar++;
- char c3 = '\0';
- if ((c1 == 0x28) && (c2 == 0x42)) // ASCII
- key = "ISO 2022 IR 6";
- else if ((c1 == 0x2d) && (c2 == 0x41)) // Latin alphabet No. 1
- key = "ISO 2022 IR 100";
- else if ((c1 == 0x2d) && (c2 == 0x42)) // Latin alphabet No. 2
- key = "ISO 2022 IR 101";
- else if ((c1 == 0x2d) && (c2 == 0x43)) // Latin alphabet No. 3
- key = "ISO 2022 IR 109";
- else if ((c1 == 0x2d) && (c2 == 0x44)) // Latin alphabet No. 4
- key = "ISO 2022 IR 110";
- else if ((c1 == 0x2d) && (c2 == 0x4c)) // Cyrillic
- key = "ISO 2022 IR 144";
- else if ((c1 == 0x2d) && (c2 == 0x47)) // Arabic
- key = "ISO 2022 IR 127";
- else if ((c1 == 0x2d) && (c2 == 0x46)) // Greek
- key = "ISO 2022 IR 126";
- else if ((c1 == 0x2d) && (c2 == 0x48)) // Hebrew
- key = "ISO 2022 IR 138";
- else if ((c1 == 0x2d) && (c2 == 0x4d)) // Latin alphabet No. 5
- key = "ISO 2022 IR 148";
- else if ((c1 == 0x2d) && (c2 == 0x62)) // Latin alphabet No. 9
- key = "ISO 2022 IR 203";
- else if ((c1 == 0x29) && (c2 == 0x49)) // Japanese, JIS X0201, G1 set (Katakana)
- key = "ISO 2022 IR 13";
- else if ((c1 == 0x28) && (c2 == 0x4a)) // Japanese, JIS X0201, G0 set (Romaji, i.e. ASCII)
- key = "ISO 2022 IR 13";
- else if ((c1 == 0x2d) && (c2 == 0x54)) // Thai
- key = "ISO 2022 IR 166";
- else if ((c1 == 0x24) && (c2 == 0x42)) // Japanese (multi-byte), JIS X0208 (Kanji)
- key = "ISO 2022 IR 87";
- else if ((c1 == 0x24) && (c2 == 0x28)) // Japanese (multi-byte), JIS X0212 (Supplementary Kanji set)
- {
- escLength = 3;
- // do we still have another character in the string?
- if (pos + escLength < fromLength)
- {
- c3 = *currentChar++;
- if (c3 == 0x44)
- key = "ISO 2022 IR 159";
- }
- }
- else if ((c1 == 0x24) && (c2 == 0x29)) // might be Korean or Chinese
- {
- escLength = 3;
- // do we still have another character in the string?
- if (pos + escLength < fromLength)
- {
- c3 = *currentChar++;
- if (c3 == 0x43) // Korean (single- and multi-byte)
- key = "ISO 2022 IR 149";
- else if (c3 == 0x41) // Simplified Chinese (multi-byte)
- key = "ISO 2022 IR 58";
- }
- }
- // check whether a valid escape sequence has been found
- if (key.empty())
- {
- OFOStringStream stream;
- stream << "Cannot convert character set: Illegal escape sequence 'ESC "
- << STD_NAMESPACE dec << STD_NAMESPACE setfill('0')
- << STD_NAMESPACE setw(2) << OFstatic_cast(int, c1 >> 4) << "/"
- << STD_NAMESPACE setw(2) << OFstatic_cast(int, c1 & 0x0f) << " "
- << STD_NAMESPACE setw(2) << OFstatic_cast(int, c2 >> 4) << "/"
- << STD_NAMESPACE setw(2) << OFstatic_cast(int, c2 & 0x0f);
- if (escLength == 3)
- {
- stream << " " << STD_NAMESPACE setw(2) << OFstatic_cast(int, c3 >> 4) << "/"
- << STD_NAMESPACE setw(2) << OFstatic_cast(int, c3 & 0x0f);
- }
- stream << "' found" << OFStringStream_ends;
- OFSTRINGSTREAM_GETOFSTRING(stream, message)
- status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str());
- }
- if (status.good())
- {
- DCMDATA_TRACE(" Switching to character set '" << key << "'");
- T_EncodingConvertersMap::const_iterator it = EncodingConverters.find(key);
- // check whether the descriptor was found in the map, i.e. properly declared in (0008,0005)
- if (it != EncodingConverters.end())
- {
- converter = it->second;
- // special case: these Japanese character sets replace the ASCII part (G0 code area),
- // so according to DICOM PS 3.5 Section 6.2.1.2 an explicit switch to the default is required
- checkDelimiters = (key != "ISO 2022 IR 87") && (key != "ISO 2022 IR 159");
- // determine number of bytes per character (used by the selected character set)
- if ((key == "ISO 2022 IR 87") || (key == "ISO 2022 IR 159") || (key == "ISO 2022 IR 58"))
- {
- DCMDATA_TRACE(" Now using 2 bytes per character");
- bytesPerChar = 2;
- }
- else if (key == "ISO 2022 IR 149")
- {
- DCMDATA_TRACE(" Now using 1 or 2 bytes per character");
- bytesPerChar = 0; // special handling for single- and multi-byte
- } else {
- DCMDATA_TRACE(" Now using 1 byte per character");
- bytesPerChar = 1;
- }
- } else {
- OFOStringStream stream;
- stream << "Cannot convert character set: Escape sequence refers to character set '" << key << "' that "
- "was not declared in SpecificCharacterSet (0008,0005)" << OFStringStream_ends;
- OFSTRINGSTREAM_GETOFSTRING(stream, message)
- status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str());
- }
- }
- pos += escLength;
- }
- // check whether the escape sequence was complete
- if (status.good() && (pos >= fromLength))
- {
- OFOStringStream stream;
- stream << "Cannot convert character set: Incomplete escape sequence (" << (escLength + 1)
- << " bytes expected) at the end of the string to be converted" << OFStringStream_ends;
- OFSTRINGSTREAM_GETOFSTRING(stream, message)
- status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str());
- }
- // do not copy the escape sequence to the output
- firstChar = currentChar;
- }
- // the HT, LF, FF, CR character or other delimiters (depending on the VR) also cause a switch
- else if (isDelimiter)
- {
// output some debug information
DCMDATA_TRACE(" Appending delimiter '"
<< convertToLengthLimitedOctalString(currentChar - 1 /* identical to c0 */, 1)
<< "' to the output");
// don't forget to append the delimiter
toString += c0;
- // use the default descriptor again (see DICOM PS 3.5)
- if (converter != DefaultEncodingConverter)
- {
- DCMDATA_TRACE(" Switching back to the default character set (because a delimiter was found)");
- converter = DefaultEncodingConverter;
- checkDelimiters = OFTrue;
- }
// start new sub-string after delimiter
firstChar = currentChar;
}
- // skip remaining bytes of current character (if any)
- else if (bytesPerChar != 1)
- {
- const size_t skipBytes = (bytesPerChar > 0) ? (bytesPerChar - 1) : ((c0 & 0x80) ? 1 : 0);
- if (pos + skipBytes < fromLength)
- currentChar += skipBytes;
- pos += skipBytes;
- }
++pos;
}
if (status.good())
// output some debug information
DCMDATA_TRACE(" Converting remaining sub-string '"
<< convertToLengthLimitedOctalString(firstChar, convertLength) << "'");
+ status = DefaultEncodingConverter.convertString(firstChar, convertLength, toString, OFFalse /*clearMode*/);
+ if (status.bad())
+ DCMDATA_TRACE(" -> ERROR: " << status.text());
+ }
+ }
+ }
+ return status;
+}
+
+
+OFCondition DcmSpecificCharacterSet::convertStringWithCodeExtensions(const char *fromString,
+ const size_t fromLength,
+ OFString &toString,
+ const OFString &delimiters,
+ const OFBool hasEscapeChar)
+{
+ OFCondition status = EC_Normal;
+ // any delimiters defined?
+ if (delimiters.empty())
+ {
+ // case 3: code extensions used, but no delimiters defined
+ DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
+ << convertToLengthLimitedOctalString(fromString, fromLength)
+ << "' (with code extensions)");
+ } else {
+ // case 4: code extensions used and delimiters defined
+ DCMDATA_DEBUG("DcmSpecificCharacterSet: Converting '"
+ << convertToLengthLimitedOctalString(fromString, fromLength)
+ << "' (with " << (hasEscapeChar ? "code extensions and " : "")
+ << "delimiters '" << delimiters << "')");
+ }
+ // code extensions according to ISO 2022 (possibly) used, so we need to check
+ // for particular escape sequences in order to switch between character sets
+ toString.clear();
+ size_t pos = 0;
+ // some (extended) character sets use more than 1 byte per character
+ // (however, the default character set always uses a single byte)
+ unsigned char bytesPerChar = 1;
+ // check whether '=' is a delimiter, as it is used in PN values
+ OFBool isFirstGroup = (delimiters.find('=') != OFString_npos);
+ // by default, we expect that delimiters can be checked by their corresponding ASCII codes
+ // (this implies that the default character set is not "ISO 2022 IR 87" or "ISO 2022 IR 159")
+ OFBool checkDelimiters = OFTrue;
+ const char *firstChar = fromString;
+ const char *currentChar = fromString;
+ // initially, use the default descriptor
+ OFCharacterEncoding converter = DefaultEncodingConverter;
+ DCMDATA_TRACE(" Starting with the default character set");
+ // iterate over all characters of the string (as long as there is no error)
+ while ((pos < fromLength) && status.good())
+ {
+ const char c0 = *currentChar++;
+ // check for characters ESC, HT, LF, FF, CR or any other specified delimiter
+ const OFBool isEscape = (c0 == '\033');
+ const OFBool isDelimiter = checkDelimiters &&
+ ((c0 == '\011') || (c0 == '\012') || (c0 == '\014') || (c0 == '\015') || (delimiters.find(c0) != OFString_npos));
+ if (isEscape || isDelimiter)
+ {
+ // convert the sub-string (before the delimiter) with the current character set
+ const size_t convertLength = currentChar - firstChar - 1;
+ if (convertLength > 0)
+ {
+ // output some debug information
+ DCMDATA_TRACE(" Converting sub-string '"
+ << convertToLengthLimitedOctalString(firstChar, convertLength) << "'");
status = converter.convertString(firstChar, convertLength, toString, OFFalse /*clearMode*/);
if (status.bad())
DCMDATA_TRACE(" -> ERROR: " << status.text());
}
+ // check whether this was the first component group of a PN value
+ if (isDelimiter && (c0 == '='))
+ isFirstGroup = OFFalse;
}
+ // the ESC character is used to explicitly switch between character sets
+ if (isEscape)
+ {
+ // report a warning as this is a violation of DICOM PS 3.5 Section 6.2.1
+ if (isFirstGroup)
+ {
+ DCMDATA_WARN("DcmSpecificCharacterSet: Escape sequences shall not be used "
+ << "in the first component group of a Person Name (PN), using them anyway");
+ }
+ // we need at least two more characters to determine the new character set
+ size_t escLength = 2;
+ if (pos + escLength < fromLength)
+ {
+ OFString key;
+ const char c1 = *currentChar++;
+ const char c2 = *currentChar++;
+ char c3 = '\0';
+ if ((c1 == 0x28) && (c2 == 0x42)) // ASCII
+ key = "ISO 2022 IR 6";
+ else if ((c1 == 0x2d) && (c2 == 0x41)) // Latin alphabet No. 1
+ key = "ISO 2022 IR 100";
+ else if ((c1 == 0x2d) && (c2 == 0x42)) // Latin alphabet No. 2
+ key = "ISO 2022 IR 101";
+ else if ((c1 == 0x2d) && (c2 == 0x43)) // Latin alphabet No. 3
+ key = "ISO 2022 IR 109";
+ else if ((c1 == 0x2d) && (c2 == 0x44)) // Latin alphabet No. 4
+ key = "ISO 2022 IR 110";
+ else if ((c1 == 0x2d) && (c2 == 0x4c)) // Cyrillic
+ key = "ISO 2022 IR 144";
+ else if ((c1 == 0x2d) && (c2 == 0x47)) // Arabic
+ key = "ISO 2022 IR 127";
+ else if ((c1 == 0x2d) && (c2 == 0x46)) // Greek
+ key = "ISO 2022 IR 126";
+ else if ((c1 == 0x2d) && (c2 == 0x48)) // Hebrew
+ key = "ISO 2022 IR 138";
+ else if ((c1 == 0x2d) && (c2 == 0x4d)) // Latin alphabet No. 5
+ key = "ISO 2022 IR 148";
+ else if ((c1 == 0x2d) && (c2 == 0x62)) // Latin alphabet No. 9
+ key = "ISO 2022 IR 203";
+ else if ((c1 == 0x29) && (c2 == 0x49)) // Japanese, JIS X0201, G1 set (Katakana)
+ key = "ISO 2022 IR 13";
+ else if ((c1 == 0x28) && (c2 == 0x4a)) // Japanese, JIS X0201, G0 set (Romaji, i.e. ASCII)
+ key = "ISO 2022 IR 13";
+ else if ((c1 == 0x2d) && (c2 == 0x54)) // Thai
+ key = "ISO 2022 IR 166";
+ else if ((c1 == 0x24) && (c2 == 0x42)) // Japanese (multi-byte), JIS X0208 (Kanji)
+ key = "ISO 2022 IR 87";
+ else if ((c1 == 0x24) && (c2 == 0x28)) // Japanese (multi-byte), JIS X0212 (Supplementary Kanji set)
+ {
+ escLength = 3;
+ // do we still have another character in the string?
+ if (pos + escLength < fromLength)
+ {
+ c3 = *currentChar++;
+ if (c3 == 0x44)
+ key = "ISO 2022 IR 159";
+ }
+ }
+ else if ((c1 == 0x24) && (c2 == 0x29)) // might be Korean or Chinese
+ {
+ escLength = 3;
+ // do we still have another character in the string?
+ if (pos + escLength < fromLength)
+ {
+ c3 = *currentChar++;
+ if (c3 == 0x43) // Korean (single- and multi-byte)
+ key = "ISO 2022 IR 149";
+ else if (c3 == 0x41) // Simplified Chinese (multi-byte)
+ key = "ISO 2022 IR 58";
+ }
+ }
+ // check whether a valid escape sequence has been found
+ if (key.empty())
+ {
+ OFOStringStream stream;
+ stream << "Cannot convert character set: Illegal escape sequence 'ESC "
+ << STD_NAMESPACE dec << STD_NAMESPACE setfill('0')
+ << STD_NAMESPACE setw(2) << OFstatic_cast(int, c1 >> 4) << "/"
+ << STD_NAMESPACE setw(2) << OFstatic_cast(int, c1 & 0x0f) << " "
+ << STD_NAMESPACE setw(2) << OFstatic_cast(int, c2 >> 4) << "/"
+ << STD_NAMESPACE setw(2) << OFstatic_cast(int, c2 & 0x0f);
+ if (escLength == 3)
+ {
+ stream << " " << STD_NAMESPACE setw(2) << OFstatic_cast(int, c3 >> 4) << "/"
+ << STD_NAMESPACE setw(2) << OFstatic_cast(int, c3 & 0x0f);
+ }
+ stream << "' found" << OFStringStream_ends;
+ OFSTRINGSTREAM_GETOFSTRING(stream, message)
+ status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str());
+ }
+ if (status.good())
+ {
+ DCMDATA_TRACE(" Switching to character set '" << key << "'");
+ T_EncodingConvertersMap::const_iterator it = EncodingConverters.find(key);
+ // check whether the descriptor was found in the map, i.e. properly declared in (0008,0005)
+ if (it != EncodingConverters.end())
+ {
+ converter = it->second;
+ // special case: these Japanese character sets replace the ASCII part (G0 code area),
+ // so according to DICOM PS 3.5 Section 6.2.1.2 an explicit switch to the default is required
+ checkDelimiters = (key != "ISO 2022 IR 87") && (key != "ISO 2022 IR 159");
+ // determine number of bytes per character (used by the selected character set)
+ if ((key == "ISO 2022 IR 87") || (key == "ISO 2022 IR 159") || (key == "ISO 2022 IR 58"))
+ {
+ DCMDATA_TRACE(" Now using 2 bytes per character");
+ bytesPerChar = 2;
+ }
+ else if (key == "ISO 2022 IR 149")
+ {
+ DCMDATA_TRACE(" Now using 1 or 2 bytes per character");
+ bytesPerChar = 0; // special handling for single- and multi-byte
+ } else {
+ DCMDATA_TRACE(" Now using 1 byte per character");
+ bytesPerChar = 1;
+ }
+ } else {
+ OFOStringStream stream;
+ stream << "Cannot convert character set: Escape sequence refers to character set '" << key << "' that "
+ "was not declared in SpecificCharacterSet (0008,0005)" << OFStringStream_ends;
+ OFSTRINGSTREAM_GETOFSTRING(stream, message)
+ status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str());
+ }
+ }
+ pos += escLength;
+ }
+ // check whether the escape sequence was complete
+ if (status.good() && (pos >= fromLength))
+ {
+ OFOStringStream stream;
+ stream << "Cannot convert character set: Incomplete escape sequence (" << (escLength + 1)
+ << " bytes expected) at the end of the string to be converted" << OFStringStream_ends;
+ OFSTRINGSTREAM_GETOFSTRING(stream, message)
+ status = makeOFCondition(OFM_dcmdata, EC_CODE_CannotConvertCharacterSet, OF_error, message.c_str());
+ }
+ // do not copy the escape sequence to the output
+ firstChar = currentChar;
+ }
+ // the HT, LF, FF, CR character or other delimiters (depending on the VR) also cause a switch
+ else if (isDelimiter)
+ {
+ // output some debug information
+ DCMDATA_TRACE(" Appending delimiter '"
+ << convertToLengthLimitedOctalString(currentChar - 1 /* identical to c0 */, 1)
+ << "' to the output");
+ // don't forget to append the delimiter
+ toString += c0;
+ // use the default descriptor again (see DICOM PS 3.5)
+ if (converter != DefaultEncodingConverter)
+ {
+ DCMDATA_TRACE(" Switching back to the default character set (because a delimiter was found)");
+ converter = DefaultEncodingConverter;
+ checkDelimiters = OFTrue;
+ }
+ // start new sub-string after delimiter
+ firstChar = currentChar;
+ }
+ // skip remaining bytes of current character (if any)
+ else if (bytesPerChar != 1)
+ {
+ const size_t skipBytes = (bytesPerChar > 0) ? (bytesPerChar - 1) : ((c0 & 0x80) ? 1 : 0);
+ if (pos + skipBytes < fromLength)
+ currentChar += skipBytes;
+ pos += skipBytes;
+ }
+ ++pos;
}
if (status.good())
{
- // finally, output some debug information
- if (DestinationEncoding == "UTF-8")
+ // convert any remaining characters from the input string
+ const size_t convertLength = currentChar - firstChar;
+ if (convertLength > 0)
{
- // output code points only in case of UTF-8 output
- DCMDATA_TRACE("Converted result in " << DestinationEncoding << " is '"
- << convertToLengthLimitedOctalString(toString.c_str(), toString.length()) << "' ("
- << countCharactersInUTF8String(toString) << " code points)");
- } else {
- DCMDATA_TRACE("Converted result in " << DestinationEncoding << " is '"
- << convertToLengthLimitedOctalString(toString.c_str(), toString.length()) << "'");
+ // output some debug information
+ DCMDATA_TRACE(" Converting remaining sub-string '"
+ << convertToLengthLimitedOctalString(firstChar, convertLength) << "'");
+ status = converter.convertString(firstChar, convertLength, toString, OFFalse /*clearMode*/);
+ if (status.bad())
+ DCMDATA_TRACE(" -> ERROR: " << status.text());
}
}
return status;
}
-OFBool DcmSpecificCharacterSet::isConversionAvailable()
-{
- // just call the appropriate function from the underlying class
- return OFCharacterEncoding::isLibraryAvailable();
-}
-
-
-size_t DcmSpecificCharacterSet::countCharactersInUTF8String(const OFString &utf8String)
-{
- // just call the appropriate function from the underlying class
- return OFCharacterEncoding::countCharactersInUTF8String(utf8String);
-}
OFBool DcmSpecificCharacterSet::checkForEscapeCharacter(const char *strValue,
// return string by-value (in order to avoid another parameter)
return octalString;
}
+
+
+// static helper functions
+
+OFBool DcmSpecificCharacterSet::isConversionAvailable()
+{
+ // just call the appropriate function from the underlying class
+ return OFCharacterEncoding::isLibraryAvailable();
+}
+
+
+size_t DcmSpecificCharacterSet::countCharactersInUTF8String(const OFString &utf8String)
+{
+ // just call the appropriate function from the underlying class
+ return OFCharacterEncoding::countCharactersInUTF8String(utf8String);
+}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SOCKET_H
#ifndef DCOMPAT_SYS_SOCKET_H_
#define DCOMPAT_SYS_SOCKET_H_
{ UID_JPEGLSLossyTransferSyntax, "JPEGLSNearLossless", "JPEGLSLossy", { EUS_DICOM, EUV_Standard, EUT_TransferSyntax, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_RLELosslessTransferSyntax, "RLELossless", "RLELossless", { EUS_DICOM, EUV_Standard, EUT_TransferSyntax, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_DeflatedExplicitVRLittleEndianTransferSyntax, "DeflatedExplicitVRLittleEndian", "DeflatedLittleEndianExplicit", { EUS_DICOM, EUV_Standard, EUT_TransferSyntax, EUST_other, EUIT_other, UID_PROP_NONE } },
+ { UID_DeflatedImageFrameCompressionTransferSyntax, "DeflatedImageFrameCompression", "DeflatedImageFrameCompression", { EUS_DICOM, EUV_Standard, EUT_TransferSyntax, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_JPEG2000LosslessOnlyTransferSyntax, "JPEG2000Lossless", "JPEG2000LosslessOnly", { EUS_DICOM, EUV_Standard, EUT_TransferSyntax, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_JPEG2000TransferSyntax, "JPEG2000", "JPEG2000", { EUS_DICOM, EUV_Standard, EUT_TransferSyntax, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax, "JPEG2000MCLossless", "JPEG2000MulticomponentLosslessOnly", { EUS_DICOM, EUV_Standard, EUT_TransferSyntax, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_VLSlideCoordinatesMicroscopicImageStorage, "VLSlideCoordinatesMicroscopicImageStorage", "VLSlideCoordinatesMicroscopicImageStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Image, UID_PROP_NONE } },
{ UID_VLWholeSlideMicroscopyImageStorage, "VLWholeSlideMicroscopyImageStorage", "VLWholeSlideMicroscopyImageStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Image, UID_PROP_ENHANCED_MF } },
{ UID_VolumeRenderingVolumetricPresentationStateStorage, "VolumeRenderingVolumetricPresentationStateStorage", "VolumeRenderingVolumetricPresentationStateStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_PresentationState, UID_PROP_NONE } },
+ { UID_WaveformAcquisitionPresentationStateStorage, "WaveformAcquisitionPresentationStateStorage", "WaveformAcquisitionPresentationStateStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_PresentationState, UID_PROP_NONE } },
{ UID_WaveformAnnotationSRStorage, "WaveformAnnotationSRStorage", "WaveformAnnotationSRStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_StructuredReport, UID_PROP_NONE } },
+ { UID_WaveformPresentationStateStorage, "WaveformPresentationStateStorage", "WaveformPresentationStateStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_PresentationState, UID_PROP_NONE } },
{ UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, "WideFieldOphthalmicPhotographyStereographicProjectionImageStorage", "WideFieldOphthalmicPhotographyStereographicProjectionImageStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Image, UID_PROP_NONE } },
{ UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage, "WideFieldOphthalmicPhotography3DCoordinatesImageStorage", "WideFieldOphthalmicPhotography3DCoordinatesImageStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Image, UID_PROP_NONE } },
{ UID_XADefinedProcedureProtocolStorage, "XADefinedProcedureProtocolStorage", "XADefinedProcedureProtocolStorage", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_other, UID_PROP_NON_PATIENT | UID_PROP_NO_DIR_RECORD } },
{ UID_DICONDE_EddyCurrentMultiframeImageStorage, "EddyCurrentMultiFrameImageStorage", "DICONDE_EddyCurrentMultiframeImageStorage", { EUS_DICONDE, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Image, UID_PROP_NONE } },
{ UID_DICONDE_ThermographyImageStorage, "ThermographyImageStorage", "DICONDE_ThermographyImageStorage", { EUS_DICONDE, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Image, UID_PROP_NONE } },
{ UID_DICONDE_ThermographyMultiFrameImageStorage, "ThermographyMultiFrameImageStorage", "DICONDE_ThermographyMultiFrameImageStorage", { EUS_DICONDE, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Image, UID_PROP_NONE } },
+ { UID_DICONDE_UltrasoundWaveformStorage, "UltrasoundWaveformStorage", "DICONDE_UltrasoundWaveformStorage", { EUS_DICONDE, EUV_Standard, EUT_SOPClass, EUST_Storage, EUIT_Waveform, UID_PROP_NONE } },
// Query/Retrieve
{ UID_FINDPatientRootQueryRetrieveInformationModel, "PatientRootQueryRetrieveInformationModelFind", "FINDPatientRootQueryRetrieveInformationModel", { EUS_DICOM, EUV_Standard, EUT_SOPClass, EUST_QueryRetrieve, EUIT_other, UID_PROP_NONE } },
{ UID_DRAFT_UnifiedProcedureStepPushSOPClass, "UnifiedProcedureStepPushTrial", "DRAFT_UnifiedProcedureStepPushSOPClass", { EUS_DICOM, EUV_Draft, EUT_SOPClass, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_DRAFT_UnifiedProcedureStepWatchSOPClass, "UnifiedProcedureStepWatchTrial", "DRAFT_UnifiedProcedureStepWatchSOPClass", { EUS_DICOM, EUV_Draft, EUT_SOPClass, EUST_other, EUIT_other, UID_PROP_NONE } },
{ UID_DRAFT_UnifiedProcedureStepPullSOPClass, "UnifiedProcedureStepPullTrial", "DRAFT_UnifiedProcedureStepPullSOPClass", { EUS_DICOM, EUV_Draft, EUT_SOPClass, EUST_other, EUIT_other, UID_PROP_NONE } },
- { UID_DRAFT_UnifiedProcedureStepEventSOPClass, "UnifiedProcedureStepEventTrial", "DRAFT_UnifiedProcedureStepEventSOPClass", { EUS_DICOM, EUV_Draft, EUT_SOPClass, EUST_other, EUIT_other, UID_PROP_NONE } },
-
- // end of the list
- { NULL, NULL, NULL, { EUS_other, EUV_other, EUT_other, EUST_other, EUIT_other, UID_PROP_NONE } }
+ { UID_DRAFT_UnifiedProcedureStepEventSOPClass, "UnifiedProcedureStepEventTrial", "DRAFT_UnifiedProcedureStepEventSOPClass", { EUS_DICOM, EUV_Draft, EUT_SOPClass, EUST_other, EUIT_other, UID_PROP_NONE } }
};
static const int uidNameMap_size = OFstatic_cast(int, sizeof(uidNameMap) / sizeof(UIDNameMap));
UID_VLSlideCoordinatesMicroscopicImageStorage,
UID_VLWholeSlideMicroscopyImageStorage,
UID_VolumeRenderingVolumetricPresentationStateStorage,
+ UID_WaveformAcquisitionPresentationStateStorage,
UID_WaveformAnnotationSRStorage,
+ UID_WaveformPresentationStateStorage,
UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage,
UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage,
UID_XAPerformedProcedureProtocolStorage,
UID_DICONDE_EddyCurrentMultiframeImageStorage,
UID_DICONDE_ThermographyImageStorage,
UID_DICONDE_ThermographyMultiFrameImageStorage,
+ UID_DICONDE_UltrasoundWaveformStorage,
NULL
};
// UID_TractographyResultsStorage,
// UID_VariableModalityLUTSoftcopyPresentationStateStorage,
// UID_VolumeRenderingVolumetricPresentationStateStorage,
+// UID_WaveformAcquisitionPresentationStateStorage,
// UID_WaveformAnnotationSRStorage,
+// UID_WaveformPresentationStateStorage,
// UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage,
// UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage,
// UID_XAPerformedProcedureProtocolStorage,
// UID_DICONDE_EddyCurrentMultiframeImageStorage,
// UID_DICONDE_ThermographyImageStorage,
// UID_DICONDE_ThermographyMultiFrameImageStorage,
+// UID_DICONDE_UltrasoundWaveformStorage,
NULL
};
{ UID_VLSlideCoordinatesMicroscopicImageStorage, "VLs", 768 * 576 * 3 },
{ UID_VLWholeSlideMicroscopyImageStorage, "VLw", 10000 * 10000 * 3 },
{ UID_VolumeRenderingVolumetricPresentationStateStorage, "VPv", 4096 },
+ { UID_WaveformAcquisitionPresentationStateStorage, "PSq", 4096 },
{ UID_WaveformAnnotationSRStorage, "SRw", 4096 },
+ { UID_WaveformPresentationStateStorage, "PSw", 4096 },
{ UID_WideFieldOphthalmicPhotographyStereographicProjectionImageStorage, "OWs", 768 * 576 * 3 },
{ UID_WideFieldOphthalmicPhotography3DCoordinatesImageStorage, "OW3", 768 * 576 * 3 },
{ UID_XADefinedProcedureProtocolStorage, "PPxd", 4096 },
{ UID_DICONDE_EddyCurrentImageStorage, "EC", 512 * 512 },
{ UID_DICONDE_EddyCurrentMultiframeImageStorage, "ECm", 512 * 512 },
{ UID_DICONDE_ThermographyImageStorage, "TG", 512 * 512 },
- { UID_DICONDE_ThermographyMultiFrameImageStorage, "TGm", 512 * 512 }
+ { UID_DICONDE_ThermographyMultiFrameImageStorage, "TGm", 512 * 512 },
+ { UID_DICONDE_UltrasoundWaveformStorage, "UW", 4096 }
};
static const int numberOfDcmModalityTableEntries = OFstatic_cast(int, sizeof(modalities) / sizeof(DcmModalityTable));
* Public Function Prototypes
*/
-
const char *dcmSOPClassUIDToModality(const char *sopClassUID,
const char *defaultValue)
{
return defaultValue;
}
+
/*
** dcmFindUIDFromName(const char* name)
** Return the UID of a name.
return defaultValue;
}
+
/*
** dcmFindUIDFromKeyword(const char* keyword)
** Return the UID of a keyword.
/*
*
- * Copyright (C) 1994-2022, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmDecimalString::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition status = EC_Normal;
+
/* always write JSON Opener */
writeJsonOpener(out, format);
OFBool isValid;
if (!isEmpty())
{
/* write element value */
- OFString bulkDataValue;
- if (format.asBulkDataURI(getTag(), bulkDataValue))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, bulkDataValue);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ status = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
{
OFString value;
OFString vmstring = "1";
- OFCondition status = getOFString(value, 0L);
+ status = getOFString(value, 0L);
if (status.bad())
return status;
format.printValuePrefix(out);
switch (format.getJsonNumStringPolicy())
{
case DcmJsonFormat::NSP_auto:
- if (isValid) DcmJsonFormat::printNumberDecimal(out, value);
- else DcmJsonFormat::printValueString(out, value);
+ if (isValid)
+ DcmJsonFormat::printNumberDecimal(out, value);
+ else
+ {
+ DCMDATA_WARN("encountered illegal DS value '" << value << "', converting to JSON string");
+ DcmJsonFormat::printValueString(out, value);
+ }
break;
case DcmJsonFormat::NSP_always_number:
- if (isValid) DcmJsonFormat::printNumberDecimal(out, value);
- else return EC_CannotWriteStringAsJsonNumber;
+ if (isValid)
+ DcmJsonFormat::printNumberDecimal(out, value);
+ else
+ {
+ DCMDATA_WARN("encountered illegal DS value '" << value << "', aborting conversion to JSON");
+ return EC_CannotWriteStringAsJSONNumber;
+ }
break;
case DcmJsonFormat::NSP_always_string:
+ if (!isValid)
+ {
+ DCMDATA_WARN("encountered illegal DS value '" << value << "', converting to JSON string");
+ }
DcmJsonFormat::printValueString(out, value);
break;
}
switch (format.getJsonNumStringPolicy())
{
case DcmJsonFormat::NSP_auto:
- if (isValid) DcmJsonFormat::printNumberDecimal(out, value);
- else DcmJsonFormat::printValueString(out, value);
+ if (isValid)
+ DcmJsonFormat::printNumberDecimal(out, value);
+ else
+ {
+ DCMDATA_WARN("encountered illegal DS value '" << value << "', converting to JSON string");
+ DcmJsonFormat::printValueString(out, value);
+ }
break;
case DcmJsonFormat::NSP_always_number:
- if (isValid) DcmJsonFormat::printNumberDecimal(out, value);
- else return EC_CannotWriteStringAsJsonNumber;
+ if (isValid)
+ DcmJsonFormat::printNumberDecimal(out, value);
+ else
+ {
+ DCMDATA_WARN("encountered illegal DS value '" << value << "', aborting conversion to JSON");
+ return EC_CannotWriteStringAsJSONNumber;
+ }
break;
case DcmJsonFormat::NSP_always_string:
+ if (!isValid)
+ {
+ DCMDATA_WARN("encountered illegal DS value '" << value << "', converting to JSON string");
+ }
DcmJsonFormat::printValueString(out, value);
break;
}
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return status;
}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmFloatingPointDouble::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition status = EC_Normal;
+
/* always write JSON Opener */
writeJsonOpener(out, format);
+
/* write element value (if non-empty) */
if (!isEmpty())
{
- OFCondition status;
const unsigned long vm = getVM();
if (! format.getJsonExtensionEnabled())
}
}
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ status = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
+ OFString value;
status = getOFString(value, 0L);
if (status.bad()) return status;
format.printValuePrefix(out);
}
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return status;
}
/*
*
- * Copyright (C) 1994-2021, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmFloatingPointSingle::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition status = EC_Normal;
+
/* always write JSON Opener */
writeJsonOpener(out, format);
+
/* write element value (if non-empty) */
if (!isEmpty())
{
- OFCondition status;
const unsigned long vm = getVM();
if (! format.getJsonExtensionEnabled())
}
}
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ status = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
+ OFString value;
status = getOFString(value, 0L);
if (status.bad()) return status;
format.printValuePrefix(out);
format.printValueSuffix(out);
}
}
+
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return status;
}
/*
*
- * Copyright (C) 1994-2022, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmIntegerString::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition status = EC_Normal;
+
/* always write JSON Opener */
writeJsonOpener(out, format);
OFBool isValid;
if (!isEmpty())
{
/* write element value */
- OFString bulkDataValue;
- if (format.asBulkDataURI(getTag(), bulkDataValue))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, bulkDataValue);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ status = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
{
OFString value;
OFString vmstring = "1";
- OFCondition status = getOFString(value, 0L);
+ status = getOFString(value, 0L);
if (status.bad())
return status;
format.printValuePrefix(out);
switch (format.getJsonNumStringPolicy())
{
case DcmJsonFormat::NSP_auto:
- if (isValid) DcmJsonFormat::printNumberInteger(out, value);
- else DcmJsonFormat::printValueString(out, value);
+ if (isValid)
+ DcmJsonFormat::printNumberInteger(out, value);
+ else
+ {
+ DCMDATA_WARN("encountered illegal IS value '" << value << "', converting to JSON string");
+ DcmJsonFormat::printValueString(out, value);
+ }
break;
case DcmJsonFormat::NSP_always_number:
if (isValid) DcmJsonFormat::printNumberInteger(out, value);
- else return EC_CannotWriteStringAsJsonNumber;
+ else
+ {
+ DCMDATA_WARN("encountered illegal IS value '" << value << "', aborting conversion to JSON");
+ return EC_CannotWriteStringAsJSONNumber;
+ }
break;
case DcmJsonFormat::NSP_always_string:
+ if (!isValid)
+ {
+ DCMDATA_WARN("encountered illegal IS value '" << value << "', converting to JSON string");
+ }
DcmJsonFormat::printValueString(out, value);
break;
}
switch (format.getJsonNumStringPolicy())
{
case DcmJsonFormat::NSP_auto:
- if (isValid) DcmJsonFormat::printNumberInteger(out, value);
- else DcmJsonFormat::printValueString(out, value);
+ if (isValid)
+ DcmJsonFormat::printNumberInteger(out, value);
+ else
+ {
+ DCMDATA_WARN("encountered illegal IS value '" << value << "', converting to JSON string");
+ DcmJsonFormat::printValueString(out, value);
+ }
break;
case DcmJsonFormat::NSP_always_number:
- if (isValid) DcmJsonFormat::printNumberInteger(out, value);
- else return EC_CannotWriteStringAsJsonNumber;
+ if (isValid)
+ DcmJsonFormat::printNumberInteger(out, value);
+ else
+ {
+ DCMDATA_WARN("encountered illegal IS value '" << value << "', aborting conversion to JSON");
+ return EC_CannotWriteStringAsJSONNumber;
+ }
break;
case DcmJsonFormat::NSP_always_string:
+ if (!isValid)
+ {
+ DCMDATA_WARN("encountered illegal IS value '" << value << "', converting to JSON string");
+ }
DcmJsonFormat::printValueString(out, value);
break;
}
/* write JSON Closer */
writeJsonCloser(out, format);
/* always report success */
- return EC_Normal;
+ return status;
}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* swapping is applied as necessary. */
void* thisData = myThis->getValue();
void* rhsData = myRhs->getValue();
- return memcmp(thisData, rhsData, thisLength);
+ return compareValues(thisData, rhsData, thisLength);
}
OFCondition DcmOtherByteOtherWord::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition result = EC_Normal;
+
/* write JSON Opener */
writeJsonOpener(out, format);
+
/* for an empty value field, we do not need to do anything */
if (getLengthField() > 0)
{
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
- {
- /* return defined BulkDataURI */
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
- }
- else
- {
- /* encode binary data as Base64 */
- format.printInlineBinaryPrefix(out);
- out << "\"";
- /* adjust byte order to little endian */
- Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
- OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField()));
- out << "\"";
- }
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ result = format.writeBinaryAttribute(out, getTag(), getLengthField(), byteValues);
}
+
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return result;
+}
+
+
+// ********************************
+
+int DcmOtherByteOtherWord::compareValues(const void* myValue,
+ const void* rhsValue,
+ const unsigned long valLength) const
+{
+ /* check for null pointers before comparing */
+ if (myValue == OFnullptr || rhsValue == OFnullptr)
+ {
+ /* handle null pointers appropriately, e.g., treat null as less than non-null */
+ if (myValue == OFnullptr && rhsValue == OFnullptr)
+ return 0; // both are null, considered equal
+ else if (myValue == OFnullptr)
+ return -1; // null is less than non-null
+ else
+ return 1; // non-null is greater than null
+ }
+ else {
+ /* Proceed with the comparison */
+ return memcmp(myValue, rhsValue, valLength);
+ }
}
/*
*
- * Copyright (C) 2013-2020, OFFIS e.V.
+ * Copyright (C) 2013-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofuuid.h"
#include "dcmtk/ofstd/ofstd.h"
+#include "dcmtk/ofstd/ofmath.h"
#include "dcmtk/dcmdata/dcvrod.h"
#include "dcmtk/dcmdata/dcswap.h"
#include "dcmtk/dcmdata/dcjson.h"
+#include <cmath>
// ********************************
// ********************************
+/* need to check for "Not a Number" in order to avoid possible output of "-nan" */
+static inline void checkAndOutputFloatValue(STD_NAMESPACE ostream &out,
+ const Float64 value)
+{
+ if (OFMath::isnan(value))
+ out << "nan";
+ else
+ out << value;
+}
OFCondition DcmOtherDouble::writeXML(STD_NAMESPACE ostream &out,
const size_t flags)
{
/* increase default precision - see DcmFloatingPointDouble::print() */
const STD_NAMESPACE streamsize oldPrecision = out.precision(17);
+ /* use the standard "C" locale for proper decimal point */
+ const STD_NAMESPACE locale oldLocale = out.imbue(STD_NAMESPACE locale("C"));
/* print float values with separators */
- out << (*(floatValues++));
+ checkAndOutputFloatValue(out, *(floatValues++));
for (unsigned long i = 1; i < count; i++)
- out << "\\" << (*(floatValues++));
- /* reset i/o manipulators */
+ {
+ out << "\\";
+ checkAndOutputFloatValue(out, *(floatValues++));
+ }
+ /* reset i/o manipulators and locale */
out.precision(oldPrecision);
+ out.imbue(oldLocale);
}
}
}
OFCondition DcmOtherDouble::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
- /* always write JSON Opener */
+ OFCondition result = EC_Normal;
+
+ /* write JSON Opener */
writeJsonOpener(out, format);
+
/* for an empty value field, we do not need to do anything */
if (getLengthField() > 0)
{
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
- {
- /* return defined BulkDataURI */
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
- }
- else
- {
- /* encode binary data as Base64 */
- format.printInlineBinaryPrefix(out);
- out << "\"";
- /* adjust byte order to little endian */
- Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
- OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField()));
- out << "\"";
- }
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ result = format.writeBinaryAttribute(out, getTag(), getLengthField(), byteValues);
}
- /* write JSON Closer */
+
+ /* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return result;
}
/*
*
- * Copyright (C) 2002-2020, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofuuid.h"
#include "dcmtk/ofstd/ofstd.h"
+#include "dcmtk/ofstd/ofmath.h"
#include "dcmtk/dcmdata/dcjson.h"
#include "dcmtk/dcmdata/dcvrof.h"
#include "dcmtk/dcmdata/dcswap.h"
+#include <cmath>
// ********************************
// ********************************
+/* need to check for "Not a Number" in order to avoid possible output of "-nan" */
+static inline void checkAndOutputFloatValue(STD_NAMESPACE ostream &out,
+ const Float32 value)
+{
+ if (OFMath::isnan(value))
+ out << "nan";
+ else
+ out << value;
+}
OFCondition DcmOtherFloat::writeXML(STD_NAMESPACE ostream &out,
const size_t flags)
if (count > 0)
{
/* increase default precision - see DcmFloatingPointSingle::print() */
- const STD_NAMESPACE streamsize oldPrecision = out.precision(8);
+ const STD_NAMESPACE streamsize oldPrecision = out.precision(9);
+ /* use the standard "C" locale for proper decimal point */
+ const STD_NAMESPACE locale oldLocale = out.imbue(STD_NAMESPACE locale("C"));
/* print float values with separators */
- out << (*(floatValues++));
+ checkAndOutputFloatValue(out, *(floatValues++));
for (unsigned long i = 1; i < count; i++)
- out << "\\" << (*(floatValues++));
- /* reset i/o manipulators */
+ {
+ out << "\\";
+ checkAndOutputFloatValue(out, *(floatValues++));
+ }
+ /* reset i/o manipulators and locale */
out.precision(oldPrecision);
+ out.imbue(oldLocale);
}
}
}
OFCondition DcmOtherFloat::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
- /* always write JSON Opener */
+ OFCondition result = EC_Normal;
+
+ /* write JSON Opener */
writeJsonOpener(out, format);
+
/* for an empty value field, we do not need to do anything */
if (getLengthField() > 0)
{
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
- {
- /* return defined BulkDataURI */
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
- }
- else
- {
- /* encode binary data as Base64 */
- format.printInlineBinaryPrefix(out);
- out << "\"";
- /* adjust byte order to little endian */
- Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
- OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField()));
- out << "\"";
- }
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ result = format.writeBinaryAttribute(out, getTag(), getLengthField(), byteValues);
}
- /* always write JSON Closer */
+
+ /* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return result;
}
/*
*
- * Copyright (C) 2016-2019, OFFIS e.V.
+ * Copyright (C) 2016-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmOtherLong::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition result = EC_Normal;
+
/* write JSON Opener */
writeJsonOpener(out, format);
+
/* for an empty value field, we do not need to do anything */
if (getLengthField() > 0)
{
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
- {
- /* return defined BulkDataURI */
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
- }
- else
- {
- /* encode binary data as Base64 */
- format.printInlineBinaryPrefix(out);
- out << "\"";
- /* adjust byte order to little endian */
- Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
- OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField()));
- out << "\"";
- }
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ result = format.writeBinaryAttribute(out, getTag(), getLengthField(), byteValues);
}
+
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return result;
}
/*
*
- * Copyright (C) 2019, OFFIS e.V.
+ * Copyright (C) 2019-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmOther64bitVeryLong::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition result = EC_Normal;
+
/* write JSON Opener */
writeJsonOpener(out, format);
+
/* for an empty value field, we do not need to do anything */
if (getLengthField() > 0)
{
- OFString value;
- if (format.asBulkDataURI(getTag(), value))
- {
- /* return defined BulkDataURI */
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, value);
- }
- else
- {
- /* encode binary data as Base64 */
- format.printInlineBinaryPrefix(out);
- out << "\"";
- /* adjust byte order to little endian */
- Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
- OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField()));
- out << "\"";
- }
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ result = format.writeBinaryAttribute(out, getTag(), getLengthField(), byteValues);
}
+
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return result;
}
/*
*
- * Copyright (C) 1997-2020, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// Get values, always compare in Little Endian byte order (only relevant for OW)
void* myValue = myThis->getValue(EBO_LittleEndian);
void* rhsValue = myRhs->getValue(EBO_LittleEndian);
- result = memcmp(myValue, rhsValue, myLength);
+ result = compareValues(myValue, rhsValue, myLength);
if (result < 0)
return -1;
else if (result > 0)
/*
*
- * Copyright (C) 2019-2024, OFFIS e.V.
+ * Copyright (C) 2019-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmSigned64bitVeryLong::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition status = EC_Normal;
+
/* always write JSON Opener */
writeJsonOpener(out, format);
{
/* write element value */
- OFString bulkDataValue;
- if (format.asBulkDataURI(getTag(), bulkDataValue))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, bulkDataValue);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ status = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
OFString value;
Sint64 v = 0;
- OFCondition status = getOFString(value, 0L);
+ status = getOFString(value, 0L);
if (status.bad()) return status;
format.printValuePrefix(out);
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return status;
}
/*
*
- * Copyright (C) 2019-2024, OFFIS e.V.
+ * Copyright (C) 2019-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition DcmUnsigned64bitVeryLong::writeJson(STD_NAMESPACE ostream &out,
DcmJsonFormat &format)
{
+ OFCondition status = EC_Normal;
+
/* always write JSON Opener */
writeJsonOpener(out, format);
{
/* write element value */
- OFString bulkDataValue;
- if (format.asBulkDataURI(getTag(), bulkDataValue))
+ if (format.asBulkDataURI(getTag(), getLength()))
{
- format.printBulkDataURIPrefix(out);
- DcmJsonFormat::printString(out, bulkDataValue);
+ /* adjust byte order to little endian */
+ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian));
+ status = format.writeBulkData(out, getTag(), getLengthField(), byteValues);
}
else
{
OFString value;
Uint64 v = 0;
- OFCondition status = getOFString(value, 0L);
+ status = getOFString(value, 0L);
if (status.bad()) return status;
format.printValuePrefix(out);
/* write JSON Closer */
writeJsonCloser(out, format);
- /* always report success */
- return EC_Normal;
+ return status;
}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcuid.h"
#include <cstring>
+#define DCXFER_DEFAULT_MIME_TYPE "application/dicom"
+#define DCXFER_DEFAULT_EXTENSION ".bin"
+
typedef struct
{
const char *xferID;
Uint32 JPEGProcess12;
E_StreamCompression streamCompression;
E_XferValidity xferValidity;
+ const char *mimeType;
+ const char *filenameExtension;
} S_XferNames;
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
// entry #1
{ "", // internal type, no UID defined
OFFalse,
0L, 0L,
ESC_none,
- EXV_Internal
+ EXV_Internal,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
// entry #2
{ UID_LittleEndianExplicitTransferSyntax,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
// entry #3
{ UID_BigEndianExplicitTransferSyntax,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Retired // retired with Supplement 98
+ EXV_Retired, // retired with Supplement 98
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
// entry #4
{ UID_EncapsulatedUncompressedExplicitVRLittleEndianTransferSyntax,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
// entry #5
{ UID_JPEGProcess1TransferSyntax,
OFTrue,
1L, 1L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jpeg",
+ ".jpeg"
},
// entry #6
{ UID_JPEGProcess2_4TransferSyntax,
OFTrue,
2L, 4L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jpeg",
+ ".jpeg"
},
// entry #7
{ UID_JPEGProcess3_5TransferSyntax,
OFTrue,
3L, 5L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #8
{ UID_JPEGProcess6_8TransferSyntax,
OFTrue,
6L, 8L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #9
{ UID_JPEGProcess7_9TransferSyntax,
OFTrue,
7L, 9L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #10
{ UID_JPEGProcess10_12TransferSyntax,
OFTrue,
10L, 12L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #11
{ UID_JPEGProcess11_13TransferSyntax,
OFTrue,
11L, 13L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #12
{ UID_JPEGProcess14TransferSyntax,
OFTrue,
14, 14L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jpeg",
+ ".jpeg"
},
// entry #13
{ UID_JPEGProcess15TransferSyntax,
OFTrue,
15L, 15L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #14
{ UID_JPEGProcess16_18TransferSyntax,
OFTrue,
16L, 18L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #15
{ UID_JPEGProcess17_19TransferSyntax,
OFTrue,
17L, 19L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #16
{ UID_JPEGProcess20_22TransferSyntax,
OFTrue,
20L, 22L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #17
{ UID_JPEGProcess21_23TransferSyntax,
OFTrue,
21L, 23L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #18
{ UID_JPEGProcess24_26TransferSyntax,
OFTrue,
24L, 26L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #19
{ UID_JPEGProcess25_27TransferSyntax,
OFTrue,
25L, 27L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #20
{ UID_JPEGProcess28TransferSyntax,
OFTrue,
28L, 28L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #21
{ UID_JPEGProcess29TransferSyntax,
OFTrue,
29L, 29L,
ESC_none,
- EXV_Retired // retired with Supplement 61
+ EXV_Retired, // retired with Supplement 61
+ "image/jpeg",
+ ".jpeg"
},
// entry #22
{ UID_JPEGProcess14SV1TransferSyntax,
OFTrue,
14L, 14L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jpeg",
+ ".jpeg"
},
// entry #23
{ UID_RLELosslessTransferSyntax,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/dicom-rle",
+ ".dicom-rle"
},
// entry #24
{ UID_DeflatedExplicitVRLittleEndianTransferSyntax,
#else
ESC_unsupported,
#endif
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
// entry #25
+ { UID_DeflatedImageFrameCompressionTransferSyntax,
+ "Deflated Image Frame Compression",
+ EXS_DeflatedImageFrameCompression,
+ EBO_LittleEndian,
+ EBO_LittleEndian,
+ EVT_Explicit,
+ EPE_Encapsulated,
+ EPC_LosslessCompressed,
+ OFFalse,
+ 0L, 0L,
+ ESC_none,
+ EXV_Standard,
+ "application/x-deflate",
+ ".x-deflate"
+ },
+ // entry #26
{ UID_JPEGLSLosslessTransferSyntax,
"JPEG-LS Lossless",
EXS_JPEGLSLossless,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jls",
+ ".jls"
},
- // entry #26
+ // entry #27
{ UID_JPEGLSLossyTransferSyntax,
"JPEG-LS Lossy (Near-lossless)",
EXS_JPEGLSLossy,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jls",
+ ".jls"
},
- // entry #27
+ // entry #28
{ UID_JPEG2000LosslessOnlyTransferSyntax,
"JPEG 2000 (Lossless only)",
EXS_JPEG2000LosslessOnly,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jp2",
+ ".jp2"
},
- // entry #28
+ // entry #29
{ UID_JPEG2000TransferSyntax,
"JPEG 2000 (Lossless or Lossy)",
EXS_JPEG2000,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jp2",
+ ".jp2"
},
- // entry #29
+ // entry #30
{ UID_JPEG2000Part2MulticomponentImageCompressionLosslessOnlyTransferSyntax,
"JPEG 2000 Part 2 Multicomponent Image Compression (Lossless only)",
EXS_JPEG2000MulticomponentLosslessOnly,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jpx",
+ ".jpx"
},
- // entry #30
+ // entry #31
{ UID_JPEG2000Part2MulticomponentImageCompressionTransferSyntax,
"JPEG 2000 Part 2 Multicomponent Image Compression (Lossless or Lossy)",
EXS_JPEG2000Multicomponent,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jpx",
+ ".jpx"
},
- // entry #31
+ // entry #32
{ UID_JPIPReferencedTransferSyntax,
"JPIP Referenced",
EXS_JPIPReferenced,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
- // entry #32
+ // entry #33
{ UID_JPIPReferencedDeflateTransferSyntax,
"JPIP Referenced Deflate",
EXS_JPIPReferencedDeflate,
#else
ESC_unsupported,
#endif
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
- // entry #33
+ // entry #34
{ UID_MPEG2MainProfileAtMainLevelTransferSyntax,
"MPEG2 Main Profile @ Main Level", // changed with DICOM 2016e to: MPEG2 Main Profile / Main Level
EXS_MPEG2MainProfileAtMainLevel,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mpeg",
+ ".mpeg"
},
- // entry #34
+ // entry #35
{ UID_FragmentableMPEG2MainProfileMainLevelTransferSyntax,
"Fragmentable MPEG2 Main Profile / Main Level",
EXS_FragmentableMPEG2MainProfileMainLevel,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mpeg",
+ ".mpeg"
},
- // entry #35
+ // entry #36
{ UID_MPEG2MainProfileAtHighLevelTransferSyntax,
"MPEG2 Main Profile @ High Level", // changed with DICOM 2016e to: MPEG2 Main Profile / High Level
EXS_MPEG2MainProfileAtHighLevel,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mpeg",
+ ".mpeg"
},
- // entry #36
+ // entry #37
{ UID_FragmentableMPEG2MainProfileHighLevelTransferSyntax,
"Fragmentable MPEG2 Main Profile / High Level",
EXS_FragmentableMPEG2MainProfileHighLevel,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mpeg",
+ ".mpeg"
},
- // entry #37
+ // entry #38
{ UID_MPEG4HighProfileLevel4_1TransferSyntax,
"MPEG-4 AVC/H.264 High Profile / Level 4.1",
EXS_MPEG4HighProfileLevel4_1,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #38
+ // entry #39
{ UID_FragmentableMPEG4HighProfileLevel4_1TransferSyntax,
"Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.1",
EXS_FragmentableMPEG4HighProfileLevel4_1,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #39
+ // entry #40
{ UID_MPEG4BDcompatibleHighProfileLevel4_1TransferSyntax,
"MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1",
EXS_MPEG4BDcompatibleHighProfileLevel4_1,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #40
+ // entry #41
{ UID_FragmentableMPEG4BDcompatibleHighProfileLevel4_1TransferSyntax,
"Fragmentable MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1",
EXS_FragmentableMPEG4BDcompatibleHighProfileLevel4_1,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #41
+ // entry #42
{ UID_MPEG4HighProfileLevel4_2_For2DVideoTransferSyntax,
"MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video",
EXS_MPEG4HighProfileLevel4_2_For2DVideo,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #42
+ // entry #43
{ UID_FragmentableMPEG4HighProfileLevel4_2_For2DVideoTransferSyntax,
"Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video",
EXS_FragmentableMPEG4HighProfileLevel4_2_For2DVideo,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #43
+ // entry #44
{ UID_MPEG4HighProfileLevel4_2_For3DVideoTransferSyntax,
"MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video",
EXS_MPEG4HighProfileLevel4_2_For3DVideo,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #44
+ // entry #45
{ UID_FragmentableMPEG4HighProfileLevel4_2_For3DVideoTransferSyntax,
"Fragmentable MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video",
EXS_FragmentableMPEG4HighProfileLevel4_2_For3DVideo,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #45
+ // entry #46
{ UID_MPEG4StereoHighProfileLevel4_2TransferSyntax,
"MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2",
EXS_MPEG4StereoHighProfileLevel4_2,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #46
+ // entry #47
{ UID_FragmentableMPEG4StereoHighProfileLevel4_2TransferSyntax,
"Fragmentable MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2",
EXS_FragmentableMPEG4StereoHighProfileLevel4_2,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/mp4",
+ ".mp4"
},
- // entry #47
+ // entry #48
{ UID_HEVCMainProfileLevel5_1TransferSyntax,
"HEVC/H.265 Main Profile / Level 5.1",
EXS_HEVCMainProfileLevel5_1,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/H265",
+ ".H265"
},
- // entry #48
+ // entry #49
{ UID_HEVCMain10ProfileLevel5_1TransferSyntax,
"HEVC/H.265 Main 10 Profile / Level 5.1",
EXS_HEVCMain10ProfileLevel5_1,
OFTrue,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "video/H265",
+ ".H265"
},
- // entry #49
+ // entry #50
{ UID_JPEGXLLosslessTransferSyntax,
"JPEG XL Lossless",
EXS_JPEGXLLossless,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jxl",
+ ".jxl"
},
- // entry #50
+ // entry #51
{ UID_JPEGXLJPEGRecompressionTransferSyntax,
"JPEG XL JPEG Recompression",
EXS_JPEGXLJPEGRecompression,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jxl",
+ ".jxl"
},
- // entry #51
+ // entry #52
{ UID_JPEGXLTransferSyntax,
"JPEG XL",
EXS_JPEGXL,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jxl",
+ ".jxl"
},
- // entry #52
+ // entry #53
{ UID_HighThroughputJPEG2000ImageCompressionLosslessOnlyTransferSyntax,
"High-Throughput JPEG 2000 Image Compression (Lossless Only)",
EXS_HighThroughputJPEG2000LosslessOnly,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jphc",
+ ".jphc"
},
- // entry #53
+ // entry #54
{ UID_HighThroughputJPEG2000RPCLImageCompressionLosslessOnlyTransferSyntax,
"High-Throughput JPEG 2000 with RPCL Options Image Compression (Lossless Only)",
EXS_HighThroughputJPEG2000withRPCLOptionsLosslessOnly,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jphc",
+ ".jphc"
},
- // entry #54
+ // entry #55
{ UID_HighThroughputJPEG2000ImageCompressionTransferSyntax,
"High-Throughput JPEG 2000 Image Compression",
EXS_HighThroughputJPEG2000,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ "image/jphc",
+ ".jphc"
},
- // entry #55
+ // entry #56
{ UID_JPIPHTJ2KReferencedTransferSyntax,
"JPIP HTJ2K Referenced",
EXS_JPIPHTJ2KReferenced,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
- // entry #56
+ // entry #57
{ UID_JPIPHTJ2KReferencedDeflateTransferSyntax,
"JPIP HTJ2K Referenced Deflate",
EXS_JPIPHTJ2KReferencedDeflate,
#else
ESC_unsupported,
#endif
- EXV_Standard
+ EXV_Standard,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
},
- // entry #57
+ // entry #58
{ UID_PrivateGE_LEI_WithBigEndianPixelDataTransferSyntax,
"Private GE Little Endian Implicit with big endian pixel data",
EXS_PrivateGE_LEI_WithBigEndianPixelData,
OFFalse,
0L, 0L,
ESC_none,
- EXV_Private
+ EXV_Private,
+ DCXFER_DEFAULT_MIME_TYPE,
+ DCXFER_DEFAULT_EXTENSION
}
};
JPEGProcess8(0L),
JPEGProcess12(0L),
streamCompression(ESC_none),
- xferValidity(EXV_unknown)
+ xferValidity(EXV_unknown),
+ mimeType(DCXFER_DEFAULT_MIME_TYPE),
+ filenameExtension(DCXFER_DEFAULT_EXTENSION)
{
/* casting the enum to an integer should be safe */
const int i = OFstatic_cast(int, xfer);
JPEGProcess12 = XferNames[i].JPEGProcess12;
streamCompression = XferNames[i].streamCompression;
xferValidity = XferNames[i].xferValidity;
+ mimeType = XferNames[i].mimeType;
+ filenameExtension = XferNames[i].filenameExtension;
}
}
JPEGProcess8(0L),
JPEGProcess12(0L),
streamCompression(ESC_none),
- xferValidity(EXV_unknown)
+ xferValidity(EXV_unknown),
+ mimeType(DCXFER_DEFAULT_MIME_TYPE),
+ filenameExtension(DCXFER_DEFAULT_EXTENSION)
{
if (xferName_xferID != NULL)
{
JPEGProcess12 = XferNames[i].JPEGProcess12;
streamCompression = XferNames[i].streamCompression;
xferValidity = XferNames[i].xferValidity;
+ mimeType = XferNames[i].mimeType;
+ filenameExtension = XferNames[i].filenameExtension;
}
}
}
JPEGProcess8(newXfer.JPEGProcess8),
JPEGProcess12(newXfer.JPEGProcess12),
streamCompression(newXfer.streamCompression),
- xferValidity(newXfer.xferValidity)
+ xferValidity(newXfer.xferValidity),
+ mimeType(newXfer.mimeType),
+ filenameExtension(newXfer.filenameExtension)
{
}
JPEGProcess12 = XferNames[i].JPEGProcess12;
streamCompression = XferNames[i].streamCompression;
xferValidity = XferNames[i].xferValidity;
+ mimeType = XferNames[i].mimeType;
+ filenameExtension = XferNames[i].filenameExtension;
} else {
xferSyn = EXS_Unknown;
xferID = "";
JPEGProcess12 = 0L;
streamCompression = ESC_none;
xferValidity = EXV_unknown;
+ mimeType = DCXFER_DEFAULT_MIME_TYPE;
+ filenameExtension = DCXFER_DEFAULT_EXTENSION;
}
return *this;
}
JPEGProcess12 = newXfer.JPEGProcess12;
streamCompression = newXfer.streamCompression;
xferValidity = newXfer.xferValidity;
+ mimeType = newXfer.mimeType;
+ filenameExtension = newXfer.filenameExtension;
}
return *this;
}
static const flex_int16_t yy_base[2631] =
{ 0,
- 0, 38, 1130,16740,16740, 0, 1088, 6, 1083, 7,
+ 0, 38, 1130,16752,16752, 0, 1088, 6, 1083, 7,
1053, 1048, 1024, 6, 0, 1019, 1, 36, 46, 38,
74, 47, 0, 993, 75, 92, 0, 50, 0, 51,
89, 90, 0, 994, 93, 100, 101, 0, 0, 984,
5407, 0, 5041, 5398, 5412, 5419, 5426, 5431, 4, 5435,
5440, 5445, 5450, 5454, 5459, 5464, 5469, 5473, 5478, 5483,
- 5488, 5492, 5497,16740, 5522, 5537, 5547, 5559, 5567, 5579,
+ 5488, 5492, 5497,16752, 5522, 5537, 5547, 5559, 5567, 5579,
5587, 5600, 5616, 5631, 5646, 5656, 5667, 5681, 5695, 5705,
5708, 5720, 5728, 5731, 5739, 5746, 5760, 5768, 5771, 5779,
5786, 5798, 5811, 5826, 5841, 5856, 5866, 5870, 5881, 5893,
16013,16025,16037,16049,16061,16073,16085,16097,16109,16121,
16133,16145,16157,16169,16181,16193,16205,16217,16229,16241,
16253,16265,16277,16289,16301,16309,16316,16324,16327,16330,
- 16333, 5307, 5316,16340, 5320, 5381,16352,16360,16363,16370,
- 16378,16385,16393,16396,16399,16402, 5385, 5397,16409, 5420,
- 5497,16421,16429,16436,16444,16447,16450,16453,16456,16459,
+ 16333,16336, 5307,16343,16351, 5316,16358,16366,16369,16376,
+ 16384,16391,16399,16402,16405,16408,16411, 5320,16418,16426,
+ 5381,16433,16441,16448,16456,16459,16462,16465,16468,16471,
- 16462,16465,16468,16471,16474,16477,16480,16487,16499,16507,
- 16510,16517,16529,16541,16553,16561,16568,16580,16592,16604,
- 16616,16628,16640,16652,16664,16676,16688,16700,16712,16724
+ 16474,16477,16480,16483,16486,16489,16492,16499,16511,16519,
+ 16522,16529,16541,16553,16565,16573,16580,16592,16604,16616,
+ 16628,16640,16652,16664,16676,16688,16700,16712,16724,16736
} ;
static const flex_int16_t yy_def[2631] =
1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614
} ;
-static const flex_int16_t yy_nxt[16782] =
+static const flex_int16_t yy_nxt[16794] =
{ 0,
1614, 1614, 5, 1614, 30, 35, 1614, 1614, 1614, 1614,
110, 111, 112, 147, 147, 147, 147, 88, 89, 104,
1547, 1547, 1547, 1547, 1547, 1547, 1547, 486, 242, 1505,
1506, 1556, 1556, 1556, 1556, 1557, 489, 350, 1508, 1509,
- 365, 1614, 1414, 1415, 1566, 1518, 1518, 368, 245, 369,
- 1614, 1417, 1418, 1568, 1520, 1520, 50, 245, 1523, 1523,
+ 365, 1614, 1414, 1415, 1566, 1520, 1520, 368, 245, 369,
+ 1614, 1417, 1418, 1568, 1525, 1525, 50, 245, 1553, 1553,
368, 1569, 1569, 1569, 1569, 1569, 1569, 1614, 350, 50,
1569, 1569, 1569, 1569, 1569, 1569, 1573, 1573, 1573, 1573,
1573, 1573, 1573, 1573, 1573, 1573, 1573, 1573, 245, 365,
369, 486, 1585, 1505, 1506, 1582, 489, 486, 1508, 1509,
1584, 365, 489, 1414, 1415, 369, 1585, 1417, 1418, 368,
- 50, 368, 1586, 1592, 1592, 1593, 50, 368, 1594, 1525,
- 1525, 368, 50, 1551, 1551, 50, 1586, 365, 1586, 1414,
+ 50, 368, 1586, 1592, 1592, 1593, 50, 368, 1594, 1558,
+ 1558, 368, 50, 1614, 1614, 50, 1586, 365, 1586, 1414,
- 1415, 369, 1594, 1417, 1418, 1553, 1553, 486, 1586, 1505,
+ 1415, 369, 1594, 1417, 1418, 1614, 1614, 486, 1586, 1505,
1506, 489, 1614, 1508, 1509, 1614, 365, 368, 1414, 1415,
- 1614, 50, 1586, 369, 1614, 1417, 1418, 368, 1556, 1556,
+ 1614, 50, 1586, 369, 1614, 1417, 1418, 368, 1614, 1614,
486, 50, 1505, 1506, 1614, 489, 368, 1508, 1509, 365,
1614, 1414, 1415, 50, 369, 1614, 1417, 1418, 1614, 486,
368, 1505, 1506, 1614, 489, 50, 1508, 1509, 365, 368,
1415, 1614, 369, 50, 1417, 1418, 1614, 486, 368, 1505,
1506, 1614, 489, 50, 1508, 1509, 486, 368, 1505, 1506,
- 1614, 489, 50, 1508, 1509, 1558, 1558, 368, 1614, 1614,
+ 1614, 489, 50, 1508, 1509, 1614, 1614, 368, 1614, 1614,
1614, 1614, 50, 1614, 1614, 1614, 368, 1614, 1614, 1614,
1614, 50, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1511, 1614, 1614, 1614, 1614, 1511, 1512, 1512, 1512, 1513,
1614, 1614, 1614, 1513, 1513, 1513, 1614, 1614, 1614, 1614,
1513, 1514, 1514, 1514, 1515, 1515, 1515, 1516, 1516, 1516,
- 1517, 1517, 1517, 1522, 1614, 1522, 1614, 1522, 1522, 1614,
- 1614, 1614, 1614, 1614, 1522, 1527, 1614, 1527, 1614, 1527,
- 1527, 1614, 1614, 1614, 1614, 1614, 1527, 1532, 1532, 1532,
- 1537, 1537, 1537, 1538, 1614, 1614, 1614, 1538, 1538, 1538,
- 1614, 1614, 1614, 1614, 1538, 1539, 1539, 1539, 1540, 1614,
- 1614, 1614, 1540, 1540, 1540, 1614, 1614, 1614, 1614, 1540,
-
- 1541, 1541, 1541, 1542, 1542, 1542, 1546, 1546, 1546, 1550,
- 1550, 1550, 1555, 1614, 1555, 1614, 1555, 1555, 1614, 1614,
- 1614, 1614, 1614, 1555, 1560, 1614, 1560, 1614, 1560, 1560,
- 1614, 1614, 1614, 1614, 1614, 1560, 1561, 1561, 1561, 1562,
- 1614, 1614, 1614, 1562, 1562, 1562, 1614, 1614, 1614, 1614,
- 1562, 1563, 1563, 1563, 1564, 1564, 1564, 1565, 1565, 1565,
- 1567, 1567, 1567, 1572, 1572, 1572, 1576, 1576, 1576, 1577,
- 1577, 1577, 1578, 1578, 1578, 1579, 1579, 1579, 1580, 1580,
- 1580, 1581, 1581, 1581, 1583, 1583, 1583, 1587, 1587, 1587,
- 1588, 1614, 1588, 1614, 1588, 1588, 1588, 1614, 1614, 1614,
-
- 1614, 1588, 1589, 1614, 1589, 1614, 1589, 1589, 1589, 1614,
- 1614, 1614, 1614, 1589, 1590, 1590, 1590, 1591, 1591, 1591,
- 1595, 1614, 1595, 1614, 1595, 1595, 1595, 1614, 1614, 1614,
- 1614, 1595, 1596, 1614, 1596, 1614, 1596, 1596, 1596, 1614,
- 1614, 1614, 1614, 1596, 1597, 1614, 1597, 1614, 1597, 1597,
- 1597, 1614, 1614, 1614, 1614, 1597, 1598, 1614, 1598, 1614,
- 1598, 1598, 1598, 1614, 1614, 1614, 1614, 1598, 1599, 1599,
- 1599, 1600, 1614, 1600, 1614, 1600, 1600, 1600, 1614, 1614,
- 1614, 1614, 1600, 1601, 1614, 1601, 1614, 1601, 1601, 1601,
- 1614, 1614, 1614, 1614, 1601, 1602, 1614, 1602, 1614, 1602,
-
- 1602, 1602, 1614, 1614, 1614, 1614, 1602, 1603, 1614, 1603,
- 1614, 1603, 1603, 1603, 1614, 1614, 1614, 1614, 1603, 1604,
- 1614, 1604, 1614, 1604, 1604, 1604, 1614, 1614, 1614, 1614,
- 1604, 1605, 1614, 1605, 1614, 1605, 1605, 1605, 1614, 1614,
- 1614, 1614, 1605, 1606, 1614, 1606, 1614, 1606, 1606, 1606,
- 1614, 1614, 1614, 1614, 1606, 1607, 1614, 1607, 1614, 1607,
- 1607, 1607, 1614, 1614, 1614, 1614, 1607, 1608, 1614, 1608,
- 1614, 1608, 1608, 1608, 1614, 1614, 1614, 1614, 1608, 1609,
- 1614, 1609, 1614, 1609, 1609, 1609, 1614, 1614, 1614, 1614,
- 1609, 1610, 1614, 1610, 1614, 1610, 1610, 1610, 1614, 1614,
-
- 1614, 1614, 1610, 1611, 1614, 1611, 1614, 1611, 1611, 1611,
- 1614, 1614, 1614, 1614, 1611, 1612, 1614, 1612, 1614, 1612,
- 1612, 1612, 1614, 1614, 1614, 1614, 1612, 1613, 1614, 1613,
- 1614, 1613, 1613, 1613, 1614, 1614, 1614, 1614, 1613, 3,
+ 1517, 1517, 1517, 1518, 1518, 1518, 1522, 1614, 1522, 1614,
+ 1522, 1522, 1614, 1614, 1614, 1614, 1614, 1522, 1523, 1523,
+ 1523, 1527, 1614, 1527, 1614, 1527, 1527, 1614, 1614, 1614,
+ 1614, 1614, 1527, 1532, 1532, 1532, 1537, 1537, 1537, 1538,
+ 1614, 1614, 1614, 1538, 1538, 1538, 1614, 1614, 1614, 1614,
+ 1538, 1539, 1539, 1539, 1540, 1614, 1614, 1614, 1540, 1540,
+
+ 1540, 1614, 1614, 1614, 1614, 1540, 1541, 1541, 1541, 1542,
+ 1542, 1542, 1546, 1546, 1546, 1550, 1550, 1550, 1551, 1551,
+ 1551, 1555, 1614, 1555, 1614, 1555, 1555, 1614, 1614, 1614,
+ 1614, 1614, 1555, 1556, 1556, 1556, 1560, 1614, 1560, 1614,
+ 1560, 1560, 1614, 1614, 1614, 1614, 1614, 1560, 1561, 1561,
+ 1561, 1562, 1614, 1614, 1614, 1562, 1562, 1562, 1614, 1614,
+ 1614, 1614, 1562, 1563, 1563, 1563, 1564, 1564, 1564, 1565,
+ 1565, 1565, 1567, 1567, 1567, 1572, 1572, 1572, 1576, 1576,
+ 1576, 1577, 1577, 1577, 1578, 1578, 1578, 1579, 1579, 1579,
+ 1580, 1580, 1580, 1581, 1581, 1581, 1583, 1583, 1583, 1587,
+
+ 1587, 1587, 1588, 1614, 1588, 1614, 1588, 1588, 1588, 1614,
+ 1614, 1614, 1614, 1588, 1589, 1614, 1589, 1614, 1589, 1589,
+ 1589, 1614, 1614, 1614, 1614, 1589, 1590, 1590, 1590, 1591,
+ 1591, 1591, 1595, 1614, 1595, 1614, 1595, 1595, 1595, 1614,
+ 1614, 1614, 1614, 1595, 1596, 1614, 1596, 1614, 1596, 1596,
+ 1596, 1614, 1614, 1614, 1614, 1596, 1597, 1614, 1597, 1614,
+ 1597, 1597, 1597, 1614, 1614, 1614, 1614, 1597, 1598, 1614,
+ 1598, 1614, 1598, 1598, 1598, 1614, 1614, 1614, 1614, 1598,
+ 1599, 1599, 1599, 1600, 1614, 1600, 1614, 1600, 1600, 1600,
+ 1614, 1614, 1614, 1614, 1600, 1601, 1614, 1601, 1614, 1601,
+
+ 1601, 1601, 1614, 1614, 1614, 1614, 1601, 1602, 1614, 1602,
+ 1614, 1602, 1602, 1602, 1614, 1614, 1614, 1614, 1602, 1603,
+ 1614, 1603, 1614, 1603, 1603, 1603, 1614, 1614, 1614, 1614,
+ 1603, 1604, 1614, 1604, 1614, 1604, 1604, 1604, 1614, 1614,
+ 1614, 1614, 1604, 1605, 1614, 1605, 1614, 1605, 1605, 1605,
+ 1614, 1614, 1614, 1614, 1605, 1606, 1614, 1606, 1614, 1606,
+ 1606, 1606, 1614, 1614, 1614, 1614, 1606, 1607, 1614, 1607,
+ 1614, 1607, 1607, 1607, 1614, 1614, 1614, 1614, 1607, 1608,
+ 1614, 1608, 1614, 1608, 1608, 1608, 1614, 1614, 1614, 1614,
+ 1608, 1609, 1614, 1609, 1614, 1609, 1609, 1609, 1614, 1614,
+
+ 1614, 1614, 1609, 1610, 1614, 1610, 1614, 1610, 1610, 1610,
+ 1614, 1614, 1614, 1614, 1610, 1611, 1614, 1611, 1614, 1611,
+ 1611, 1611, 1614, 1614, 1614, 1614, 1611, 1612, 1614, 1612,
+ 1614, 1612, 1612, 1612, 1614, 1614, 1614, 1614, 1612, 1613,
+ 1614, 1613, 1614, 1613, 1613, 1613, 1614, 1614, 1614, 1614,
+ 1613, 3, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
- 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
- 1614
+ 1614, 1614, 1614
+
} ;
-static const flex_int16_t yy_chk[16782] =
+static const flex_int16_t yy_chk[16794] =
{ 0,
0, 0, 1, 0, 15, 17, 43, 0, 43, 43,
53, 53, 53, 70, 70, 70, 70, 39, 39, 48,
1523, 1525, 1525, 1525, 1525, 1525, 1525, 1532, 1538, 1532,
1532, 1534, 1534, 1534, 1534, 1534, 1537, 1540, 1537, 1537,
- 1546, 0, 1546, 1546, 1546, 2572, 2572, 1532, 1538, 1550,
- 0, 1550, 1550, 1550, 2573, 2573, 1537, 1540, 2575, 2575,
+ 1546, 0, 1546, 1546, 1546, 2573, 2573, 1532, 1538, 1550,
+ 0, 1550, 1550, 1550, 2576, 2576, 1537, 1540, 2588, 2588,
1546, 1551, 1551, 1551, 1551, 1551, 1551, 0, 1562, 1550,
1553, 1553, 1553, 1553, 1553, 1553, 1556, 1556, 1556, 1556,
1556, 1556, 1558, 1558, 1558, 1558, 1558, 1558, 1562, 1565,
1567, 1572, 1577, 1572, 1572, 1572, 1576, 1581, 1576, 1576,
1576, 1579, 1583, 1579, 1579, 1580, 1585, 1580, 1580, 1565,
- 1567, 1572, 1577, 1586, 1586, 1586, 1576, 1581, 1587, 2576,
- 2576, 1579, 1583, 2587, 2587, 1580, 1585, 1588, 1586, 1588,
+ 1567, 1572, 1577, 1586, 1586, 1586, 1576, 1581, 1587, 2591,
+ 2591, 1579, 1583, 0, 0, 1580, 1585, 1588, 1586, 1588,
- 1588, 1589, 1594, 1589, 1589, 2588, 2588, 1590, 1587, 1590,
+ 1588, 1589, 1594, 1589, 1589, 0, 0, 1590, 1587, 1590,
1590, 1591, 0, 1591, 1591, 0, 1595, 1588, 1595, 1595,
- 0, 1589, 1594, 1596, 0, 1596, 1596, 1590, 2590, 2590,
+ 0, 1589, 1594, 1596, 0, 1596, 1596, 1590, 0, 0,
1597, 1591, 1597, 1597, 0, 1598, 1595, 1598, 1598, 1600,
0, 1600, 1600, 1596, 1601, 0, 1601, 1601, 0, 1602,
1597, 1602, 1602, 0, 1603, 1598, 1603, 1603, 1604, 1600,
1608, 0, 1609, 1605, 1609, 1609, 0, 1610, 1606, 1610,
1610, 0, 1611, 1607, 1611, 1611, 1612, 1608, 1612, 1612,
- 0, 1613, 1609, 1613, 1613, 2591, 2591, 1610, 0, 0,
+ 0, 1613, 1609, 1613, 1613, 0, 0, 1610, 0, 0,
0, 0, 1611, 0, 0, 0, 1612, 0, 0, 0,
0, 1613, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615,
1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615, 1615,
2565, 0, 0, 0, 0, 2565, 2566, 2566, 2566, 2567,
0, 0, 0, 2567, 2567, 2567, 0, 0, 0, 0,
2567, 2568, 2568, 2568, 2569, 2569, 2569, 2570, 2570, 2570,
- 2571, 2571, 2571, 2574, 0, 2574, 0, 2574, 2574, 0,
- 0, 0, 0, 0, 2574, 2577, 0, 2577, 0, 2577,
- 2577, 0, 0, 0, 0, 0, 2577, 2578, 2578, 2578,
- 2579, 2579, 2579, 2580, 0, 0, 0, 2580, 2580, 2580,
- 0, 0, 0, 0, 2580, 2581, 2581, 2581, 2582, 0,
- 0, 0, 2582, 2582, 2582, 0, 0, 0, 0, 2582,
-
- 2583, 2583, 2583, 2584, 2584, 2584, 2585, 2585, 2585, 2586,
- 2586, 2586, 2589, 0, 2589, 0, 2589, 2589, 0, 0,
- 0, 0, 0, 2589, 2592, 0, 2592, 0, 2592, 2592,
- 0, 0, 0, 0, 0, 2592, 2593, 2593, 2593, 2594,
- 0, 0, 0, 2594, 2594, 2594, 0, 0, 0, 0,
- 2594, 2595, 2595, 2595, 2596, 2596, 2596, 2597, 2597, 2597,
- 2598, 2598, 2598, 2599, 2599, 2599, 2600, 2600, 2600, 2601,
- 2601, 2601, 2602, 2602, 2602, 2603, 2603, 2603, 2604, 2604,
- 2604, 2605, 2605, 2605, 2606, 2606, 2606, 2607, 2607, 2607,
- 2608, 0, 2608, 0, 2608, 2608, 2608, 0, 0, 0,
-
- 0, 2608, 2609, 0, 2609, 0, 2609, 2609, 2609, 0,
- 0, 0, 0, 2609, 2610, 2610, 2610, 2611, 2611, 2611,
- 2612, 0, 2612, 0, 2612, 2612, 2612, 0, 0, 0,
- 0, 2612, 2613, 0, 2613, 0, 2613, 2613, 2613, 0,
- 0, 0, 0, 2613, 2614, 0, 2614, 0, 2614, 2614,
- 2614, 0, 0, 0, 0, 2614, 2615, 0, 2615, 0,
- 2615, 2615, 2615, 0, 0, 0, 0, 2615, 2616, 2616,
- 2616, 2617, 0, 2617, 0, 2617, 2617, 2617, 0, 0,
- 0, 0, 2617, 2618, 0, 2618, 0, 2618, 2618, 2618,
- 0, 0, 0, 0, 2618, 2619, 0, 2619, 0, 2619,
-
- 2619, 2619, 0, 0, 0, 0, 2619, 2620, 0, 2620,
- 0, 2620, 2620, 2620, 0, 0, 0, 0, 2620, 2621,
- 0, 2621, 0, 2621, 2621, 2621, 0, 0, 0, 0,
- 2621, 2622, 0, 2622, 0, 2622, 2622, 2622, 0, 0,
- 0, 0, 2622, 2623, 0, 2623, 0, 2623, 2623, 2623,
- 0, 0, 0, 0, 2623, 2624, 0, 2624, 0, 2624,
- 2624, 2624, 0, 0, 0, 0, 2624, 2625, 0, 2625,
- 0, 2625, 2625, 2625, 0, 0, 0, 0, 2625, 2626,
- 0, 2626, 0, 2626, 2626, 2626, 0, 0, 0, 0,
- 2626, 2627, 0, 2627, 0, 2627, 2627, 2627, 0, 0,
-
- 0, 0, 2627, 2628, 0, 2628, 0, 2628, 2628, 2628,
- 0, 0, 0, 0, 2628, 2629, 0, 2629, 0, 2629,
- 2629, 2629, 0, 0, 0, 0, 2629, 2630, 0, 2630,
- 0, 2630, 2630, 2630, 0, 0, 0, 0, 2630, 1614,
+ 2571, 2571, 2571, 2572, 2572, 2572, 2574, 0, 2574, 0,
+ 2574, 2574, 0, 0, 0, 0, 0, 2574, 2575, 2575,
+ 2575, 2577, 0, 2577, 0, 2577, 2577, 0, 0, 0,
+ 0, 0, 2577, 2578, 2578, 2578, 2579, 2579, 2579, 2580,
+ 0, 0, 0, 2580, 2580, 2580, 0, 0, 0, 0,
+ 2580, 2581, 2581, 2581, 2582, 0, 0, 0, 2582, 2582,
+
+ 2582, 0, 0, 0, 0, 2582, 2583, 2583, 2583, 2584,
+ 2584, 2584, 2585, 2585, 2585, 2586, 2586, 2586, 2587, 2587,
+ 2587, 2589, 0, 2589, 0, 2589, 2589, 0, 0, 0,
+ 0, 0, 2589, 2590, 2590, 2590, 2592, 0, 2592, 0,
+ 2592, 2592, 0, 0, 0, 0, 0, 2592, 2593, 2593,
+ 2593, 2594, 0, 0, 0, 2594, 2594, 2594, 0, 0,
+ 0, 0, 2594, 2595, 2595, 2595, 2596, 2596, 2596, 2597,
+ 2597, 2597, 2598, 2598, 2598, 2599, 2599, 2599, 2600, 2600,
+ 2600, 2601, 2601, 2601, 2602, 2602, 2602, 2603, 2603, 2603,
+ 2604, 2604, 2604, 2605, 2605, 2605, 2606, 2606, 2606, 2607,
+
+ 2607, 2607, 2608, 0, 2608, 0, 2608, 2608, 2608, 0,
+ 0, 0, 0, 2608, 2609, 0, 2609, 0, 2609, 2609,
+ 2609, 0, 0, 0, 0, 2609, 2610, 2610, 2610, 2611,
+ 2611, 2611, 2612, 0, 2612, 0, 2612, 2612, 2612, 0,
+ 0, 0, 0, 2612, 2613, 0, 2613, 0, 2613, 2613,
+ 2613, 0, 0, 0, 0, 2613, 2614, 0, 2614, 0,
+ 2614, 2614, 2614, 0, 0, 0, 0, 2614, 2615, 0,
+ 2615, 0, 2615, 2615, 2615, 0, 0, 0, 0, 2615,
+ 2616, 2616, 2616, 2617, 0, 2617, 0, 2617, 2617, 2617,
+ 0, 0, 0, 0, 2617, 2618, 0, 2618, 0, 2618,
+
+ 2618, 2618, 0, 0, 0, 0, 2618, 2619, 0, 2619,
+ 0, 2619, 2619, 2619, 0, 0, 0, 0, 2619, 2620,
+ 0, 2620, 0, 2620, 2620, 2620, 0, 0, 0, 0,
+ 2620, 2621, 0, 2621, 0, 2621, 2621, 2621, 0, 0,
+ 0, 0, 2621, 2622, 0, 2622, 0, 2622, 2622, 2622,
+ 0, 0, 0, 0, 2622, 2623, 0, 2623, 0, 2623,
+ 2623, 2623, 0, 0, 0, 0, 2623, 2624, 0, 2624,
+ 0, 2624, 2624, 2624, 0, 0, 0, 0, 2624, 2625,
+ 0, 2625, 0, 2625, 2625, 2625, 0, 0, 0, 0,
+ 2625, 2626, 0, 2626, 0, 2626, 2626, 2626, 0, 0,
+
+ 0, 0, 2626, 2627, 0, 2627, 0, 2627, 2627, 2627,
+ 0, 0, 0, 0, 2627, 2628, 0, 2628, 0, 2628,
+ 2628, 2628, 0, 0, 0, 0, 2628, 2629, 0, 2629,
+ 0, 2629, 2629, 2629, 0, 0, 0, 0, 2629, 2630,
+ 0, 2630, 0, 2630, 2630, 2630, 0, 0, 0, 0,
+ 2630, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
- 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614, 1614,
- 1614
+ 1614, 1614, 1614
+
} ;
/* The intent behind this definition is that it'll catch
#line 1 "vrscanl.l"
/*
*
- * Copyright (C) 1997-2022, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "vrscani.h"
-#line 4896 "vrscanl.c"
+#line 4900 "vrscanl.c"
/* Make this work on windows (we don't need interactivity anyway) */
/* This seems to be a bug: The .c file won't include it, but .h will
* nevertheless.
* Our workaround: Define YY_NO_UNISTD_H in vrscani.h and make
* sure that header is included before vrscanl.h.
*/
-#line 4904 "vrscanl.c"
+#line 4908 "vrscanl.c"
#define INITIAL 0
#line 101 "vrscanl.l"
-#line 5165 "vrscanl.c"
+#line 5169 "vrscanl.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
#line 126 "vrscanl.l"
ECHO;
YY_BREAK
-#line 5329 "vrscanl.c"
+#line 5333 "vrscanl.c"
case YY_STATE_EOF(INITIAL):
yyterminate();
/*
*
- * Copyright (C) 1997-2022, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
charset_with_control_chars [\040-\176\240-\377\011\012\014\015\033]+
spaces [ ]*
zero_byte_padding \000?
-dt_offset (\-1200)|(\+1400)|(((\-((0[1-9])|(1[0-1])))|(\+((0[1-9])|(1[0-3])))){tm_minute})
+dt_offset (\-1200)|(\+1400)|(((\-((0[1-9])|(1[0-1])))|(\+((0[0-9])|(1[0-3])))){tm_minute})
da_year (18[5-9][0-9])|(19[0-9]{2})|(20[0-4][0-9])
da_year_dub [0-9]{4}
da_month (0[1-9])|(1[0-2])
tchval.cc
tdict.cc
telemlen.cc
+ tfrmsiz.cc
tests.cc
tfilter.cc
tgenuid.cc
)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(dcmdata_tests i2d dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(dcmdata_tests i2d)
# This macro parses tests.cc and registers all tests
DCMTK_ADD_TESTS(dcmdata)
../include/dcmtk/dcmdata/dclist.h ../include/dcmtk/dcmdata/dcdatset.h \
../include/dcmtk/dcmdata/dcitem.h ../include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmdata/dcdict.h ../include/dcmtk/dcmdata/dchashdi.h
+tfrmsiz.o: tfrmsiz.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../include/dcmtk/dcmdata/dcuid.h ../include/dcmtk/dcmdata/dcdefine.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../include/dcmtk/dcmdata/dcdatset.h ../include/dcmtk/dcmdata/dcitem.h \
+ ../include/dcmtk/dcmdata/dctypes.h ../include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../include/dcmtk/dcmdata/dcerror.h ../include/dcmtk/dcmdata/dcxfer.h \
+ ../include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../include/dcmtk/dcmdata/dctag.h ../include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../include/dcmtk/dcmdata/dcstack.h ../include/dcmtk/dcmdata/dclist.h \
+ ../include/dcmtk/dcmdata/dcpcache.h ../include/dcmtk/dcmdata/dcpixseq.h \
+ ../include/dcmtk/dcmdata/dcsequen.h ../include/dcmtk/dcmdata/dcelem.h \
+ ../include/dcmtk/dcmdata/dcofsetl.h ../include/dcmtk/dcmdata/dcpxitem.h \
+ ../include/dcmtk/dcmdata/dcvrobow.h ../include/dcmtk/dcmdata/dcdeftag.h \
+ ../include/dcmtk/dcmdata/dcrlerp.h ../include/dcmtk/dcmdata/dcpixel.h \
+ ../include/dcmtk/dcmdata/dcvrpobw.h ../include/dcmtk/dcmdata/dcrledrg.h
tgenuid.o: tgenuid.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/oftest.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
objs = tests.o tpread.o ti2dbmp.o tchval.o tpath.o tvrdatim.o telemlen.o tparser.o \
tdict.o tvrds.o tvrfd.o tvrui.o tvrol.o tvrov.o tvrsv.o tvruv.o tstrval.o \
tspchrs.o tvrpn.o tparent.o tfilter.o tvrcomp.o tmatch.o tnewdcme.o \
- tgenuid.o tsequen.o titem.o ttag.o txfer.o tbytestr.o
+ tgenuid.o tsequen.o titem.o ttag.o txfer.o tbytestr.o tfrmsiz.o
progs = tests
/*
*
- * Copyright (C) 2009-2016, OFFIS e.V.
+ * Copyright (C) 2009-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
CHECK_GOOD( "DT-15", DcmDateTime::checkStringValue("200907", "1") )
CHECK_GOOD( "DT-16", DcmDateTime::checkStringValue("2009", "1") )
CHECK_BAD ( "DT-17", DcmDateTime::checkStringValue("20091", "1") )
+ /* check various timezone values, both valid and invalid ones */
+ CHECK_GOOD( "DT-18", DcmDateTime::checkStringValue("202501011200+0000"));
+ CHECK_BAD ( "DT-19", DcmDateTime::checkStringValue("202501011200-0000"));
+ CHECK_GOOD( "DT-20", DcmDateTime::checkStringValue("202501011200+0100"));
+ CHECK_GOOD( "DT-21", DcmDateTime::checkStringValue("202412311200-1130"));
+ CHECK_GOOD( "DT-22", DcmDateTime::checkStringValue("202412311200-1200"));
+ CHECK_BAD ( "DT-23", DcmDateTime::checkStringValue("202412311200-1230"));
+ CHECK_GOOD( "DT-24", DcmDateTime::checkStringValue("202412311200+1200"));
+ CHECK_GOOD( "DT-25", DcmDateTime::checkStringValue("202412311200+1330"));
+ CHECK_GOOD( "DT-26", DcmDateTime::checkStringValue("202412311200+1400"));
+ CHECK_BAD ( "DT-27", DcmDateTime::checkStringValue("202412311200+1430"));
/* test "Decimal String" */
CHECK_GOOD( "DS-01", DcmDecimalString::checkStringValue(" 0", "1") )
// maximum length cannot be checked if given in characters (and not bytes)
// CHECK_BAD ( "LO-07", DcmLongString::checkStringValueu("OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany, http://www.offis.de/", "1") )
CHECK_GOOD( "LO-08", DcmLongString::checkStringValue("\\ _2_ \\ _3_ \\ _4_ \\ _5_ \\", "6") )
- CHECK_GOOD( "LO-09", DcmLongString::checkStringValue("ESC\033aping", "1") )
- CHECK_BAD ( "LO-10", DcmLongString::checkStringValue("not allowed: \r\014", "1") )
+ // actually, the following test should fail
+ CHECK_GOOD( "LO-09", DcmLongString::checkStringValue("ESC only allowed for ISO 2022 character set control sequences: \033", "1") )
+ CHECK_BAD ( "LO-10", DcmLongString::checkStringValue("also not allowed: \r\014", "1") )
/* test "Long Text" */
CHECK_GOOD( "LT-01", DcmLongText::checkStringValue(" Hello \\ 12345 \\ \344\366\374\337 ", "ISO_IR 100") )
CHECK_GOOD( "SH-08", DcmShortString::checkStringValue("\\ _2_ \\ _3_ \\ _4_ \\ _5_ \\", "6") )
CHECK_BAD ( "SH-09", DcmShortString::checkStringValue(" ", "2") )
CHECK_GOOD( "SH-10", DcmShortString::checkStringValue("", "2") )
- CHECK_GOOD( "SH-11", DcmShortString::checkStringValue("ESC\033aping", "1") )
- CHECK_BAD ( "SH-12", DcmShortString::checkStringValue("not allowed: \n\010\r\014", "1") )
+ // actually, the following test should fail
+ CHECK_GOOD( "SH-11", DcmShortString::checkStringValue("not allowed: \033", "1") )
+ CHECK_BAD ( "SH-12", DcmShortString::checkStringValue("not allowed: \n\r", "1") )
+ CHECK_BAD ( "SH-13", DcmShortString::checkStringValue("not allowed: \010\014", "1") )
/* test "Short Text" */
CHECK_GOOD( "ST-01", DcmShortText::checkStringValue(" umlaut characters are allowed: \304\326\334\344\366\374\naccented characters also: \341\340\351\350\355\354\342\352\364\rand control characters, of course, including \033=ESC ", "ISO_IR 100") )
/*
*
- * Copyright (C) 2011-2024 OFFIS e.V.
+ * Copyright (C) 2011-2025 OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFTEST_REGISTER(dcmdata_xferLookup_3);
OFTEST_REGISTER(dcmdata_xferLookup_4);
OFTEST_REGISTER(dcmdata_putOFStringAtPos);
+OFTEST_REGISTER(dcmdata_uncompressedFrameSize);
+
OFTEST_MAIN("dcmdata")
/*
*
- * Copyright (C) 2012-2020, OFFIS e.V.
+ * Copyright (C) 2012-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// test anonymous filter object
OFCHECK( DcmAttributeFilter( DCM_SOPClassUID, UID_ComputedRadiographyImageStorage )( item ) );
-#if !defined(_MSC_VER) || _MSC_VER > 1200 // iterator based filters not supported for VS <= 6.0.
// test iterator (array) based range
const char* filter_range[3] =
{
OFCHECK( ct_mr_filter( item ) );
item.putAndInsertString( DCM_SOPClassUID, UID_EnhancedCTImageStorage );
OFCHECK( !cr_ct_mr_filter( item ) );
-#endif
-
OFCHECK( DcmAttributeFilter()( item ) ); // test default constructed (allow any) filter.
}
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmdata
+ *
+ * Author: Marco Eichelberg
+ *
+ * Purpose: test program for DcmElement::getUncompressedFrameSize()
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/ofstd/oftest.h"
+#include "dcmtk/dcmdata/dcdatset.h"
+#include "dcmtk/dcmdata/dcpixseq.h"
+#include "dcmtk/dcmdata/dcpxitem.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/dcmdata/dcrlerp.h"
+#include "dcmtk/dcmdata/dcrledrg.h"
+
+OFTEST(dcmdata_uncompressedFrameSize)
+{
+ // prepare an uncompressed dataset with the attributes we need for this test
+ DcmDataset dset;
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsAllocated, 8).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsStored, 8).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_HighBit, 7).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_Columns, 256).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_Rows, 256).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_SamplesPerPixel, 3).good());
+ OFCHECK(dset.putAndInsertString(DCM_PhotometricInterpretation, "RGB").good());
+
+ // create and insert an empty pixel data element
+ DcmPixelData *px = NULL;
+ OFCHECK(NULL != (px = new DcmPixelData(DCM_PixelData)));
+ if (px)
+ {
+ OFCHECK(dset.insert(px).good());
+
+ // Tests for DcmElement::decodedBitsAllocated() with uncompressed pixel data.
+ // This should always return the first parameter (BitsAllocated), unless the
+ // second parameter (BitsStored) is larger than the first one, in which case
+ // the result should be zero.
+ OFCHECK(0 == px->decodedBitsAllocated(8, 9));
+ OFCHECK(5 == px->decodedBitsAllocated(5, 1));
+ OFCHECK(7 == px->decodedBitsAllocated(7, 1));
+ OFCHECK(8 == px->decodedBitsAllocated(8, 8));
+ OFCHECK(9 == px->decodedBitsAllocated(9, 8));
+ OFCHECK(13 == px->decodedBitsAllocated(13, 8));
+ OFCHECK(23 == px->decodedBitsAllocated(23, 8));
+ OFCHECK(255 == px->decodedBitsAllocated(255, 8));
+
+ // Tests for getUncompressedFrameSize() with an uncompressed dataset
+ Uint32 frameSize = 0;
+ OFCHECK(px->getUncompressedFrameSize(&dset, frameSize, OFTrue).good());
+ OFCHECK(196608 == frameSize);
+
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsAllocated, 12).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsStored, 12).good());
+ OFCHECK(px->getUncompressedFrameSize(&dset, frameSize, OFTrue).good());
+ OFCHECK(294912 == frameSize);
+
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsAllocated, 16).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsStored, 12).good());
+ OFCHECK(px->getUncompressedFrameSize(&dset, frameSize, OFTrue).good());
+ OFCHECK(393216 == frameSize);
+
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsAllocated, 32).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsStored, 32).good());
+ OFCHECK(px->getUncompressedFrameSize(&dset, frameSize, OFTrue).good());
+ OFCHECK(786432 == frameSize);
+
+ // set color model to YBR_FULL_422 and create a frame size indicating that we have in fact RGB
+ Uint16 *pxdata = NULL;
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsAllocated, 8).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsStored, 8).good());
+ OFCHECK(dset.putAndInsertString(DCM_PhotometricInterpretation, "YBR_FULL_422").good());
+ OFCHECK(px->createUint16Array(98304, pxdata).good());
+ OFCHECK(px->getUncompressedFrameSize(&dset, frameSize, OFTrue).good());
+ OFCHECK(196608 == frameSize);
+
+ // set color model to YBR_FULL_422 and create a frame size indicating that we have in fact uncompressed YBR_FULL_422
+ OFCHECK(px->createUint16Array(65536, pxdata).good());
+ OFCHECK(px->getUncompressedFrameSize(&dset, frameSize, OFTrue).good());
+ OFCHECK(131072 == frameSize);
+
+ // now convert the dataset to an RLE compressed one and check again
+ OFCHECK(dset.putAndInsertString(DCM_PhotometricInterpretation, "RGB").good());
+ DcmRLERepresentationParameter rle_rp;
+ DcmPixelSequence *pixelSequence = new DcmPixelSequence(DCM_PixelSequenceTag);
+ DcmPixelItem *offsetTable = new DcmPixelItem(DCM_PixelItemTag);
+ OFCHECK((NULL != pixelSequence) && (NULL != offsetTable));
+ if (pixelSequence && offsetTable)
+ {
+ pixelSequence->insert(offsetTable);
+ px->putOriginalRepresentation(EXS_RLELossless, &rle_rp, pixelSequence);
+
+ // this should fail because the RLE decoder is not registered yet,
+ // and, therefore, the computation of the uncompressed frame size will fail
+ OFCHECK(EC_InvalidValue == px->getUncompressedFrameSize(&dset, frameSize, OFTrue));
+
+ // register RLE decompression codec
+ DcmRLEDecoderRegistration::registerCodecs();
+
+ // now we can compute the frame size for the RLE compressed image
+ OFCHECK(px->getUncompressedFrameSize(&dset, frameSize, OFTrue).good());
+ OFCHECK(196608 == frameSize);
+
+ // the RLE codec should refuse the size calculation if BitsAllocated is not a multiple of 8
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsAllocated, 12).good());
+ OFCHECK(dset.putAndInsertUint16(DCM_BitsStored, 12).good());
+ OFCHECK(EC_InvalidValue == px->getUncompressedFrameSize(&dset, frameSize, OFTrue));
+
+ // these calls should now invoke the routine in the RLE codec that computes
+ // decoded bits allocated.
+ OFCHECK(0 == px->decodedBitsAllocated(8, 9));
+ OFCHECK(0 == px->decodedBitsAllocated(5, 1));
+ OFCHECK(8 == px->decodedBitsAllocated(8, 8));
+ OFCHECK(0 == px->decodedBitsAllocated(13, 8));
+ OFCHECK(16 == px->decodedBitsAllocated(16, 8));
+ OFCHECK(64 == px->decodedBitsAllocated(64, 8));
+
+ // avoid memory leak
+ DcmRLEDecoderRegistration::cleanup();
+ }
+ }
+}
/*
*
- * Copyright (C) 2019-2022, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2019-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
DcmSequenceOfItems sequence(DCM_OtherPatientIDsSequence);
/* add a large number of items to the sequence */
unsigned long counter = 0;
+ DcmItem *items[NUMBER_OF_ITEMS];
for (unsigned long i = 0; i < NUMBER_OF_ITEMS; ++i)
{
- if (sequence.insert(new DcmItem()).good())
+ items[i] = new DcmItem();
+ if (sequence.insert(items[i]).good())
++counter;
}
/* check whether that worked (for-loop shouldn't take too long) */
OFCHECK_EQUAL(counter, NUMBER_OF_ITEMS);
/* access specific items (performance should be no issue) */
- OFCHECK(sequence.getItem(0) != NULL);
- OFCHECK(sequence.getItem(2) != NULL);
+ OFCHECK(sequence.getItem(0) == items[0]);
+ OFCHECK(sequence.getItem(2) == items[2]);
OFCHECK(sequence.getItem(NUMBER_OF_ITEMS) == NULL);
- OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 1) != NULL);
- OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 2) != NULL);
+ OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 1) == items[NUMBER_OF_ITEMS - 1]);
+ OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 2) == items[NUMBER_OF_ITEMS - 2]);
+ /* insert a single item before the current item */
+ DcmItem *newItem = new DcmItem();
+ OFCHECK(sequence.insertAtCurrentPos(newItem, OFTrue /*before*/).good());
+ OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 2) == newItem);
+ /* the items after the new item should have been shifted by one */
+ OFCHECK(sequence.getItem(NUMBER_OF_ITEMS - 1) == items[NUMBER_OF_ITEMS - 2]);
+ OFCHECK(sequence.getItem(NUMBER_OF_ITEMS) == items[NUMBER_OF_ITEMS - 1]);
+ OFCHECK(sequence.getItem(NUMBER_OF_ITEMS + 1) == NULL);
}
/*
*
- * Copyright (C) 2002-2020, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/*
*
- * Copyright (C) 2019-2024, Open Connections GmbH
+ * Copyright (C) 2019-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
*/
virtual OFBool getCheckFGOnWrite();
+ /** Set whether attribute values should be checked on writing, i.e. if writing
+ * should fail if attribute values violate their VR, VM, character set or value length.
+ * A missing but required value is always considered an error, independent of this setting.
+ * If set to OFFalse, writing will always succeed, even if attribute value constraints
+ * are violated. A warning instead of an error will be printed to the logger.
+ * @param doCheck If OFTrue, attribute value errors are handled as errors on writing, if OFFalse
+ * any errors are ignored.
+ */
+ virtual void setValueCheckOnWrite(const OFBool doCheck);
+
// -------------------- creation ---------------------
/** Factory method to create an Enhanced CT object from the minimal
IODCommonInstanceReferenceModule m_CommonInstanceReferenceModule;
/// Binary frame data
- OFVector<DcmIODTypes::Frame*> m_Frames;
+ OFVector<DcmIODTypes::FrameBase*> m_Frames;
/// Multi-frame Functional Groups high level interface
FGInterface m_FGInterface;
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
/*
*
- * Copyright (C) 2019-2024, Open Connections GmbH
+ * Copyright (C) 2019-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
return FG_EC_PixelDataTooLarge;
}
const size_t numPixelsFrame = OFstatic_cast(size_t, rows) * OFstatic_cast(size_t, cols);
- const size_t numBytesFrame = m_CT.m_Frames[0]->length;
+ const size_t numBytesFrame = m_CT.m_Frames[0]->getLengthInBytes();
if (numBytesFrame != numPixelsFrame * 2)
{
DCMECT_ERROR("Invalid number of bytes per frame: Expected " << numPixelsFrame * 2 << " but got "
{
pixData->setVR(EVR_OW);
Uint16* ptr = NULL;
- size_t numBytesTotal = numBytesFrame * numFrames / 2;
+ size_t numBytesTotal = numBytesFrame * numFrames;
if (numBytesTotal <= 4294967294UL)
{
- result = pixData->createUint16Array(OFstatic_cast(Uint32, numBytesTotal), ptr);
+ result = pixData->createUint16Array(OFstatic_cast(Uint32, numBytesTotal / 2), ptr);
// copy all frames into CT's frame structure
if (ptr)
{
for (size_t f = 0; f < numFrames; ++f)
{
- memcpy(ptr, m_CT.m_Frames[f]->pixData, numBytesFrame);
+ memcpy(ptr, m_CT.m_Frames[f]->getPixelData(), numBytesFrame);
ptr += numPixelsFrame;
}
return m_Item.insert(pixData);
// Inner class that implements the writing to Concatentions via ConcatenationCreator class
// Constructor, sets parameters the visitor works on in operator()
- WriteVisitorConcatenation(EctEnhancedCT& m, Uint8*& pixData, size_t& pixDataLength)
+ WriteVisitorConcatenation(EctEnhancedCT& m, Uint16*& pixData, size_t& pixDataLength)
: m_CT(m)
, m_pixData(pixData)
, m_pixDataLength(pixDataLength)
m_CT.getRows(rows);
m_CT.getColumns(cols);
const size_t numFrames = m_CT.m_Frames.size();
- const size_t numBytesFrame = m_CT.m_Frames[0]->length;
+ const size_t numBytesFrame = m_CT.m_Frames[0]->getLengthInBytes();
// Creates the correct pixel data element, based on the image pixel module used.
m_pixDataLength = numBytesFrame * numFrames;
- m_pixData = new Uint8[m_pixDataLength];
+ m_pixData = new Uint16[m_pixDataLength / 2];
if (m_pixData)
{
- Uint8* ptr = m_pixData;
+ Uint16* ptr = m_pixData;
// copy all frames into CT's frame structure
if (ptr)
{
for (size_t f = 0; f < numFrames; ++f)
{
- memcpy(ptr, m_CT.m_Frames[f]->pixData, numBytesFrame);
- ptr += numBytesFrame;
+ memcpy(ptr, m_CT.m_Frames[f]->getPixelData(), numBytesFrame);
+ ptr += numBytesFrame / 2;
}
return EC_Normal;
}
// Members, i.e. parameters to operator()
EctEnhancedCT& m_CT;
- Uint8*& m_pixData;
+ Uint16*& m_pixData;
size_t& m_pixDataLength;
};
{
for (Uint32 n = 0; n < numFrames; n++)
{
- DcmIODTypes::Frame* f = new DcmIODTypes::Frame;
+ DcmIODTypes::Frame<Uint16>* f = new DcmIODTypes::Frame<Uint16>(numBytesFrame / 2);
if (f)
{
- f->length = numBytesFrame;
- f->pixData = new Uint8[f->length];
- memcpy(f->pixData, pixData + n * numBytesFrame / 2, numBytesFrame);
+ memcpy(f->m_pixData, pixData + n * numBytesFrame / 2, numBytesFrame);
m_CT.m_Frames.push_back(f);
}
else
{
if (!perFrameInformation.empty())
{
- OFunique_ptr<DcmIODTypes::Frame> f(new DcmIODTypes::Frame);
+ OFunique_ptr<DcmIODTypes::Frame<Uint16> > f(new DcmIODTypes::Frame<Uint16>(numPixels));
if (f)
{
- f->length = numPixels * sizeof(PixelType);
- f->pixData = new Uint8[f->length];
- memcpy(f->pixData, data, f->length);
+ memcpy(f->m_pixData, data, f->getLengthInBytes());
m_CT.m_Frames.push_back(f.release());
OFVector<FGBase*>::const_iterator fg = perFrameInformation.begin();
while (result.good() && (fg != perFrameInformation.end()))
{
if (frameNumber < m_CT.m_Frames.size())
{
- return (PixelType*)(m_CT.m_Frames[frameNumber]->pixData);
+ DcmIODTypes::Frame<PixelType>* f = OFstatic_cast(DcmIODTypes::Frame<PixelType>*, m_CT.m_Frames[frameNumber]);
+ return f->getPixelDataTyped();
}
return NULL;
}
// Helper "class" that returns Frames offering API to the pixel's frame bulk
// data by offering the dedicated data type, e.g. Float32 instead of the
-// internally stored generic Uint8 array.
+// internally stored generic Uint16 array.
//
struct EctEnhancedCT::GetFramesVisitor
{
DcmDataset dset;
ct = NULL;
- OFVector<DcmIODTypes::Frame*> frames;
+ OFVector<DcmIODTypes::FrameBase*> frames;
OFCondition result = cl.load(concatenationUID, &dset, frames);
if (result.good())
{
return m_FGInterface.getCheckOnWrite();
}
+void EctEnhancedCT::setValueCheckOnWrite(const OFBool doCheck)
+{
+ m_SynchronizationModule.setValueCheckOnWrite(doCheck);
+ m_EnhancedGeneralEquipmentModule.setValueCheckOnWrite(doCheck);
+ m_FG.setValueCheckOnWrite(doCheck);
+ m_DimensionModule.setValueCheckOnWrite(doCheck);
+ m_AcquisitionContextModule.setValueCheckOnWrite(doCheck);
+ m_CommonInstanceReferenceModule.setValueCheckOnWrite(doCheck);
+ DcmIODImage::setValueCheckOnWrite(doCheck);
+}
+
// ------------------ Creation -----------------------
OFCondition EctEnhancedCT::create(EctEnhancedCT*& ct,
return result;
}
+
// -------------------- Protected Helpers --------------------------
OFCondition EctEnhancedCT::read(DcmItem& dataset)
if (!item)
return EC_MemoryExhausted;
- Uint8* pixData = NULL;
+ Uint16* pixData = NULL;
size_t pixDataLength = 0;
OFCondition result
}
IODImage::read(dataset);
- m_SynchronizationModule.read(dataset);
+ if (m_SynchronizationModuleEnabled)
+ {
+ // Synchronization Module is type C ("Required if time synchronization was applied"),
+ // so we make it optional for reading to avoid warnings on the attributes, and then reset rules
+ // to the default state.
+ m_SynchronizationModule.makeOptional();
+ m_SynchronizationModule.read(dataset);
+ m_SynchronizationModule.resetRules();
+ }
m_EnhancedGeneralEquipmentModule.read(dataset);
m_FG.read(dataset);
m_DimensionModule.read(dataset);
)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(dcmect_tests dcmect dcmfg dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(dcmect_tests dcmect dcmfg)
# This macro parses tests.cc and registers all tests
DCMTK_ADD_TESTS(dcmect)
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
// Number of Columns of image, might be changed for testing purposes
static const Uint16 NUM_COLS = 4000;
// Number of Frames of source image, might be changed for testing purposes
-static const Uint16 NUM_FRAMES = 200;
+static const Uint16 NUM_FRAMES = 100;
// Number of Frames of in concatenation images, should not be changed since the
// dumped checked against will assume Number of Frames = 1
static const size_t NUM_FRAMES_CONCAT = 1;
DcmDataset merged;
EctEnhancedCT* mergedCT = NULL;
result = EctEnhancedCT::loadConcatenation(cl, cl.getInfo().begin()->first, mergedCT);
+ DcmItem item;
+ mergedCT->writeDataset(item);
if (result.good())
{
ConcatenationCreator cc;
/*
*
- * Copyright (C) 2024, OFFIS e.V.
+ * Copyright (C) 2024-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFTempFile tf(O_RDWR, "", "t_overflow", ".dcm");
OFCondition result;
- result = ct->saveFile("output.dcm", EXS_LittleEndianExplicit);
+ result = ct->saveFile(tf.getFilename(), EXS_LittleEndianExplicit);
OFCHECK_MSG(result == ECT_InvalidPixelInfo, result.text());
+ delete ct;
}
static EctEnhancedCT *create()
/*
*
- * Copyright (C) 2019-2024, Open Connections GmbH
+ * Copyright (C) 2019-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/ofstd/ofcond.h"
#include "dcmtk/ofstd/offile.h"
#include "dcmtk/dcmfg/fgdefine.h"
+#include "dcmtk/dcmiod/iodtypes.h"
class DcmItem;
class DcmSequenceOfItems;
virtual OFCondition
setCfgInput(DcmItem* srcDataset, Uint8* pixelData, size_t pixelDataLength, OFBool transferOwnership);
+ /** Set input dataset with separate pixel data that should be split
+ * into a number of concatenation instances.
+ * @param srcDataset The dataset to read from (must not be NULL and not contain
+ * the Pixel Data attribute (on main level)
+ * @param pixelData Raw buffer of source pixel data
+ * @param pixelDataLength Length of pixelData buffer in bytes
+ * @param transferOwnership If OFTrue, the ConcatenationCreator class will
+ * free memory of the srcDataset and pixelData after processing.
+ * @return EC_Normal if input is considered valid (up to now), error otherwise
+ */
+ virtual OFCondition
+ setCfgInput(DcmItem* srcDataset, Uint16* pixelData, size_t pixelDataLength, OFBool transferOwnership);
+
/** Set number of frames that should go into a single concatenation instance produced.
* The last concatenation instance might have less frames. This setting also
* directly determines the number of instances produced for a specific input.
*/
virtual OFCondition configureCommon();
+ /** Prepare source pixel data (m_srcPixelData) according to the pixel data
+ * existing in the source dataset.
+ * @param srcDataset The source dataset to read from
+ * @param transferOwnership If OFTrue, this class (m_srcPixelData)
+ * takes ownership of the pixel data, i.e. frees memory on destruction.
+ * @return EC_Normal if successful, error otherwise
+ */
+ virtual OFCondition initSrcPixelData(DcmItem* srcDataset, OFBool transferOwnership);
+
private:
/// Maximum number of instances that make up a Concatenation (=2^16-1=65535),
/// before the call to this class returns).
/// Once the ConcatenationCreator creator class goes out of scope or reset() is being called,
/// it is set to NULL. If m_cfgTransferOwnership is OFTrue, memory is freed by this class, too.
- Uint8* m_srcPixelData;
+ DcmIODTypes::FrameBase* m_srcPixelData;
/// VR of pixel data extracted/derived from source dataset. EVR_OB and EVR_OW are supported.
/// Initially set to EVR_Unknown.
/*
*
- * Copyright (C) 2019-2024, Open Connections GmbH
+ * Copyright (C) 2019-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
* and a vector containing all frames of the merged instance.</li>
* </ul>
*/
+
class DCMTK_DCMFG_EXPORT ConcatenationLoader
{
* @return EC_Normal if loading Concatenation worked, error otherwise.
*/
virtual OFCondition
- load(const OFString& concatenationUID, DcmDataset* dataset, OFVector<DcmIODTypes::Frame*>& frames);
+ load(const OFString& concatenationUID, DcmDataset* dataset, OFVector<DcmIODTypes::FrameBase*>& frames);
protected:
/** Handles single file of a Concatenation and extracts structure for later
*/
virtual OFCondition insertDestinationAttributes();
+ /** Compute bytes per frame based on Rows, Columns and Bits Allocated.
+ * @param rows The number of Rows
+ * @param cols The number of Columns
+ * @param bitsAlloc The Bits Allocated value (only 1, 8 or 16 supported)
+ * @param bytes_per_frame The resulting number of bytes per frame
+ * @return EC_Normal if successful, error otherwise.
+ */
virtual OFCondition
computeBytesPerFrame(const Uint16 rows, const Uint16 cols, const Uint16 bitsAlloc, size_t& bytes_per_frame);
/// produced by the load() method. Once a merged instance is provided to
/// the caller, as a result of load(), the caller is responsible for
/// deleting the related memory.
- OFVector<DcmIODTypes::Frame*> m_Frames;
+ OFVector<DcmIODTypes::FrameBase*> m_Frames;
};
#endif // CONCATENATIONLOADER_H
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
*/
virtual void clear();
+ /** Get the number of functional groups in the set
+ * @return Number of functional groups in the set
+ */
+ virtual size_t size() const;
+
/** Find a functional group by its type
* @param fgType The type of the functional group
* @return The functional group, if found, NULL otherwise
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/config/osconfig.h"
-#include "dcmtk/dcmdata/dcdatset.h"
+#include "dcmtk/dcmdata/dcvrcs.h"
#include "dcmtk/dcmfg/fgbase.h"
#include "dcmtk/dcmiod/iodmacro.h"
#include "dcmtk/ofstd/ofstring.h"
*/
virtual ImageSOPInstanceReferenceMacro& getImageSOPInstanceReference();
+ /** Get Spatial Locations Preserved
+ * @param value Reference to variable in which the value should be stored
+ * @param pos Index of the value to get (0..vm-1), -1 for all components
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getSpatialLocationsPreserved(OFString& value, const signed long pos = 0) const;
+
+ /** Set Spatial Locations Preserved
+ * @param value Value to be set (single value only) or "" for no value
+ * @param checkValue Check 'value' for conformance with VR (CS) and VM (1) if enabled
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition setSpatialLocationsPreserved(const OFString& value, const OFBool checkValue);
+
/** Reads source image item from given item
* @param itemOfSourceImageSequence Reference to item of Source Image Sequence
* @param clearOldData If OFTue, old data in this class is cleared before reading
/// Contains the referenced images (as represented by one of the items of
/// "this" Source Image Sequence)
ImageSOPInstanceReferenceMacro m_ImageSOPInstanceReference;
+
+ /// Denotes whether spatial locations from source image have been preseved
+ DcmCodeString m_SpatialLocationsPreserved;
};
/// Iterator for traversing over items of the Source Image Sequence
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
{
public:
+
/// Type representing per-frame functional groups, i.e.\ a number of
/// functional groups assigned to each frame
typedef OFMap<Uint32, FunctionalGroups*> PerFrameGroups;
*/
virtual OFBool getCheckOnWrite();
+ /** Sets the maximum number of threads to be used for reading and writing per-frame functional groups.
+ * @param numThreads The maximum number of threads to use
+ * The number of threads will be adjusted to the number of frames, i.e.\ there will
+ * be no more threads used than one fifth the number of frames (so that each thread must at least handle
+ * 10 frames, since otherwise the overhead of starting threads would be too high). The
+ * number is adjusted on the fly.
+ */
+ virtual void setUseThreads(const Uint32 numThreads);
+
+ /** Returns the number of threads to be used for writing per-frame functional groups.
+ * @return The number of threads to use
+ */
+ virtual Uint32 getUseThreads() const;
+
protected:
/** Get shared functional group based on its type
* @param fgType The type of functional group
*/
virtual OFCondition readPerFrameFG(DcmItem& dataset);
+ virtual OFCondition readPerFrameFGParallel(DcmSequenceOfItems& perFrameFGSeq, const Uint32 numThreads);
+
+ virtual OFCondition readPerFrameFGSequential(DcmSequenceOfItems& perFrameFGSeq);
+
/** Read single functional group into the item provided
* @param fgItem The item to read from
* @param groups The resulting group after reading
* @return EC_Normal if reading was successful, error otherwise
*/
- virtual OFCondition readSingleFG(DcmItem& fgItem, FunctionalGroups& groups);
+ static OFCondition readSingleFG(DcmItem& fgItem, FunctionalGroups& groups);
/** Write Shared Functional Group Sequence to given item
* @param dataset The item to write to
*/
virtual OFCondition writePerFrameFG(DcmItem& dataset);
+ /** Write Per-Frame Functional Group Sequence to given item in parallel
+ * @param dataset The item to write to
+ * @param numThreads The maximum number of threads to use
+ * @return EC_Normal if writing was successful, error otherwise
+ */
+ virtual OFCondition writePerFrameFGParallel(DcmItem& dataset, const Uint32 numThreads);
+
+ /** Write Per-Frame Functional Group Sequence to given item in sequential mode,
+ * i.e.\ no extra threads are used.
+ * @param dataset The item to write to
+ * @return EC_Normal if writing was successful, error otherwise
+ */
+ virtual OFCondition writePerFrameFGSequential(DcmItem& dataset);
+
/** Convert a shared functional group to a per-frame one by copying the
* shared one into a per-frame one for each frame and deleting the shared one
- * aftewrards.
+ * afterwards.
* @param fgType The type of functional group to convert
* @return EC_Normal if conversion worked out, FG_EC_NoSuchGroup if such a
* group does not exist and other error otherwise. In the last case
*/
virtual OFCondition convertSharedToPerFrame(const DcmFGTypes::E_FGType fgType);
+ /** Find an adequate number of threads to use for reading and writing per-frame functional groups.
+ * The number is adjusted to the number of frames, i.e.\ there will be no more threads used
+ * than one fifth the number of frames (so that each thread must at least handle
+ * 5 frames, since otherwise the overhead of starting threads would be too high).
+ * @param numFrames The number of frames to read/write
+ * @param userThreadSetting The user-defined number of threads to use
+ * @return The adjusted number of threads to use
+ */
+ virtual Uint32 findAdequateNumberOfThreads(const Uint32 numFrames, const Uint32 userThreadSetting);
+
+ /// Threaded functional group writer, used to write per-frame functional groups
+ /// in parallel. Each thread gets assigned some frames and writes the functional groups
+ /// for those frames to the output vector.
+ struct ThreadedFGWriter : public OFThread
+ {
+ /// Vector of pairs of frame number and functional groups to write for that frame
+ OFVector<OFPair<Uint32, FunctionalGroups*> >* m_frameGroups;
+ /// Output vector, where the per-frame items are written to
+ /// (one item per frame containing all functional groups for that frame).
+ // All threads write to the same vector, so it must be protected by a mutex.
+ /// The vector is resized to the total number of frames before starting the threads.
+ OFVector<DcmItem*>* m_perFrameResultItems;
+ /// Mutex to protect the output vector
+ OFMutex* m_perFrameResultItemsMutex;
+ /// Start frame this thread should handle (inclusive, starts with 0)
+ Uint32 m_startFrame;
+ /// End frame this thread should handle (exclusive, i.e.\ the last frame
+ /// this thread handles is m_endFrame - 1)
+ Uint32 m_endFrame;
+ /// Mutex to protect error output
+ OFMutex* m_errorMutex;
+ /// Pointer to a condition variable that is set if an error occurs
+ /// during writing. This is used to signal the main thread that an error
+ /// occurred during writing. The main thread can then check the error
+ /// condition variable to see if an error occurred and handle it accordingly.
+ OFConditionConst* m_errorOccurred;
+
+ /** Initialize the thread
+ * @param frameGroups Input vector of pairs of frame number and functional groups to write for that frame
+ * @param perFrameResultItems Output vector, where the per-frame items are written to,
+ * (frame number as index, one item per frame containing all functional groups for that frame).
+ * @param perFrameResultItemsMutex Mutex to protect the output vector
+ * @param startFrame Start frame this thread should handle (inclusive, starts with 0)
+ * @param endFrame End frame this thread should handle (exclusive, i.e.\ the last frame this thread handles is m_endFrame - 1)
+ * @param errorOccurred Pointer to a condition variable that is set if an error occurs
+ * @param errorMutex Mutex to protect error output
+ */
+ void init(OFVector<OFPair<Uint32, FunctionalGroups*> >* frameGroups,
+ OFVector<DcmItem*>* perFrameResultItems,
+ OFMutex* perFrameResultItemsMutex,
+ const Uint32 startFrame,
+ const Uint32 endFrame,
+ OFConditionConst* errorOccurred,
+ OFMutex* errorMutex);
+
+ /// Default constructor
+ ThreadedFGWriter();
+
+ /// Destructor, nothing to do
+ ~ThreadedFGWriter();
+
+ /** Run method, called by OFThread::start()
+ * This method will write the functional groups for the frames assigned
+ * to this thread to the output vector. It will stop in case of an error
+ * and set the error condition variable to indicate that an error occurred.
+ */
+ void run();
+ };
+
+ /// Threaded functional group reader, used to read per-frame functional groups
+ /// in parallel. Each thread gets assigned some frames and reads the functional groups
+ /// for those frames from the input vector.
+ /// The results are stored in the output vector, which is protected by a mutex.
+ struct ThreadedFGReader : public OFThread
+ {
+ /// Input vector of per-frame items, one item per frame
+ /// containing all functional groups for that frame.
+ OFVector<DcmItem*>* m_perFrameItems;
+ /// Mutex to protect the input vector
+ OFMutex* m_perFrameItemsMutex;
+ /// Output vector of per-frame functional groups, one item per frame
+ /// containing all functional groups for that frame.
+ PerFrameGroups* m_frameResultGroups;
+ /// Mutex to protect the output vector
+ OFMutex* m_frameResultGroupsMutex;
+ /// Start frame this thread should handle (inclusive, starts with 0)
+ /// (i.e.\ the first frame this thread handles is m_startFrame)
+ Uint32 m_startFrame;
+ /// End frame this thread should handle (exclusive, i.e.\ the last frame
+ /// this thread handles is m_endFrame - 1)
+ Uint32 m_endFrame;
+ /// Mutex to protect error output
+ OFMutex* m_errorMutex;
+ /// Pointer to a condition variable that is set if an error occurs
+ /// during reading. This is used to signal the main thread that an error
+ /// occurred during reading. The main thread can then check the error
+ /// condition variable to see if an error occurred and handle it accordingly.
+ OFConditionConst* m_errorOccurred;
+ /// Pointer to the FGInterface instance to read from. This is used to
+ /// access the FGInterface methods for reading functional groups.
+ /// It is set by the init() method and used in the run() method to read
+ /// each functional group
+ FGInterface* m_fgInterfacePtr; // Pointer to the FGInterface instance to read from
+
+ /** Initialize the thread
+ * @param perFrameItems Input vector of per-frame items, one item per frame
+ * containing all functional groups for that frame.
+ * @param perFrameItemsMutex Mutex to protect the input vector
+ * @param m_frameResultGroups Output vector of per-frame functional groups,
+ * one item per frame (index = frame number) containing all functional groups for that frame.
+ * @param frameResultGroupsMutex Mutex to protect the output vector
+ * @param startFrame Start frame this thread should handle (inclusive, starts with 0)
+ * @param endFrame End frame this thread should handle (exclusive, i.e.\ the last frame this thread handles is m_endFrame - 1)
+ * @param errorMutex Mutex to protect error output
+ * @param errorOccurred Pointer to a condition variable that is set if an error occurs
+ * during reading. The main thread can check this variable to see if an error occurred.
+ * @param fgInterfacePtr Pointer to the FGInterface instance;
+ * used to access its readSingleFG() method
+ */
+ void init(OFVector<DcmItem*>* perFrameItems,
+ OFMutex* perFrameItemsMutex,
+ PerFrameGroups* m_frameResultGroups,
+ OFMutex* frameResultGroupsMutex,
+ Uint32 startFrame,
+ Uint32 endFrame,
+ OFMutex* errorMutex,
+ OFConditionConst* errorOccurred,
+ FGInterface* fgInterfacePtr);
+
+ /// Default constructor
+ ThreadedFGReader();
+
+ /// Destructor
+ ~ThreadedFGReader();
+
+ /** Run method, called by OFThread::start()
+ * This method will read the functional groups for the frames assigned
+ * to this thread from the input vector and store them in the output vector.
+ * It will stop in case of an error and set the error condition variable
+ * to indicate that an error occurred.
+ */
+ void run();
+ };
+
private:
/// Shared functional groups
FunctionalGroups m_shared;
/// If enabled, functional group structure is checked on write(). Otherwise,
/// checks are skipped.
OFBool m_checkOnWrite;
+
+ /// Maximum number of threads to use for reading and writing per-frame functional groups,
+ /// default is 1 thread (sequential writing). The number provided by the user
+ /// will be adjusted to the number of frames, i.e. there will be not more threads
+ /// used than one fifth the number of frames (so that each thread must at least handle
+ // 10 frames, since otherwise the overhead of starting threads would be too high). The
+ /// number is adjusted on the fly.
+ Uint32 m_numThreads;
};
#endif // MODMULTIFRAMEFGH_H
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
*/
virtual OFCondition getReferencedSegmentNumber(Uint16& value, const unsigned long pos = 0);
- /** Set Referenced Segment Number
+ /** Set Referenced Segment Number (starting from 1)
* @param segmentNumber Value to be set
* @return EC_Normal if successful, an error code otherwise
*/
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_ConcatenationComplete;
/// Unsupported pixel data layout
extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_UnsupportedPixelDataLayout;
+/// Parallel processing failed
+extern DCMTK_DCMFG_EXPORT const OFConditionConst FG_EC_ParallelProcessingFailed;
/*---------------------*
* class declaration *
{
public:
+
+ // --- Constants ---
+
+ /// Maximum number of frames, limited by
+ /// Number of Frames attribute which maxes out at 2^31-1.
+ static const Uint32 DCMFG_MAX_FRAMES = 2147483647;
+
// --- Type definitions ---
/** Functional group types
--- /dev/null
+/*
+ * Copyright (C) 2015-2025, Open Connections GmbH
+ *
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmfg
+ *
+ * Author: Andrey Fedorov
+ *
+ * Purpose: Abstract base class for sorting frames of a functional group
+ *
+ */
+
+#ifndef FRAMESORTER_H
+#define FRAMESORTER_H
+
+#include "dcmtk/config/osconfig.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/ofstd/ofvector.h"
+#include "dcmtk/ofstd/ofstring.h"
+#include "dcmtk/ofstd/ofmath.h"
+#include "dcmtk/dcmfg/fginterface.h"
+#include "dcmtk/dcmfg/fgplanpo.h"
+#include "dcmtk/dcmfg/fgplanor.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/dcmfg/fgtypes.h"
+
+#include <stdlib.h> // for qsort
+
+typedef OFVector<Float64> ImagePosition; // Image Position Patient
+typedef OFPair<Uint32, Float64> FrameWithPos; // DICOM frame number and Image Position Patient
+
+/** Abstract class for sorting a set of frames in a functional group. The
+ * sorting criteria are up to the actual implementation classes.
+ */
+class FrameSorter
+{
+
+public:
+
+ /** Structure that transports the results of a frame sorting operation
+ */
+ struct Results
+ {
+ /** Default constructor, initializes empty results
+ */
+ Results() :
+ errorCode(EC_Normal),
+ frameNumbers(),
+ key(DCM_UndefinedTagKey),
+ fgSequenceKey(DCM_UndefinedTagKey),
+ fgPrivateCreator() { }
+
+ /** Clear all results, i.e. reset to default state
+ */
+ void clear()
+ {
+ errorCode = EC_Normal;
+ frameNumbers.clear();
+ key = DCM_UndefinedTagKey;
+ fgSequenceKey = DCM_UndefinedTagKey;
+ fgPrivateCreator = "";
+ }
+
+ /// Error code: EC_Normal if sorting was successful, error code otherwise.
+ /// The error code should be set in any case (default: EC_Normal)
+ OFCondition errorCode;
+ /// The frame numbers, in sorted order (default: empty)
+ OFVector<Uint32> frameNumbers;
+ /// The frame positions, in sorted order, if provided
+ /// by the sorter (default: empty). If not empty, contains the same number
+ /// of items as frameNumbers.
+ OFVector<ImagePosition> framePositions;
+ /// Tag key that contains the information that was crucial for sorting.
+ /// This is especially useful for creating dimension indices. Should be
+ /// set to (0xffff,0xfff) if none was used (default).
+ DcmTagKey key;
+ /// Tag functional group sequence key that contains the tag key (see other member)
+ /// that was crucial for sorting.
+ /// This is especially useful for creating dimension indices. Should be
+ /// set to (0xffff,0xfff) if none was used (default).
+ DcmTagKey fgSequenceKey;
+ /// Tag functional group sequence's private creator string for the fgSequenceKey
+ /// result member if fgSequenceKey is a private attributes.
+ /// This is especially useful for creating dimension indices that base on private
+ /// attibutes. Should be left empty if fgSequenceKey is not private or fgSequenceKey
+ /// is not used at all (default).
+ OFString fgPrivateCreator;
+ };
+
+ /** Structure that holds Image Position (Patient) values for frames
+ */
+ struct FramePositions
+ {
+ OFVector<ImagePosition> positions;
+ };
+
+ /** Default constructor, does nothing
+ */
+ FrameSorter()
+ : m_fg(NULL)
+ {}
+
+ /** Set input data for this sorter
+ * @param fg The functional groups to work on. Ownership
+ * of pointer stays with the caller.
+ */
+ void setSorterInput(FGInterface* fg)
+ {
+ m_fg = fg;
+ }
+
+ /** Virtual default desctructor, does nothing
+ */
+ virtual ~FrameSorter() {}
+
+ /** Return a frame order that is determined by the implementation of the particular
+ * derived class. E.g. a sorting by Plane Position (Patient) could be implemented.
+ * @param results The results of the sorting procedure. Should be empty (cleared)
+ * when handed into the function.
+ */
+ virtual void sort(Results& results) =0;
+
+ /** Get description of the sorting algorithm this class uses.
+ * @return Free text description of the sorting algorithm used.
+ */
+ virtual OFString getDescription() =0;
+
+
+ // Derived classes may add further functions, e.g. to provide further parameters,
+ // like the main dataset, frame data, etc.
+
+
+protected:
+
+ /// Pointer to functional groups to work on. Not owned by this class.
+ FGInterface* m_fg;
+};
+
+/** Dummy sorter implementing the FrameSorter interface,
+ * but not doing any sorting at all. As a result it provides
+ * a list of frames in their natural order, as found in the underlying
+ * DICOM dataset. The results will not contain frame position
+ * to make this implementation as lightweight and "stupid" as possible.
+ */
+class FrameSorterIdentity : public FrameSorter
+{
+
+public:
+
+ /**
+ * Default constructor, does nothing
+ */
+ FrameSorterIdentity(){};
+
+ /**
+ * Virtual default destructor, does nothing
+ */
+ virtual ~FrameSorterIdentity()
+ {
+
+ }
+
+ /** Get description of the sorting algorithm this class uses.
+ * @return Free text description of the sorting algorithm used.
+ */
+ virtual OFString getDescription()
+ {
+ return "Returns frames in the order defined in the functional group, i.e. as defined in the image file";
+ }
+
+ /** Performs actual sorting. Does only set Results.frameNumbers and errorCode,
+ * leaving the rest untouched.
+ * @param results The results produced by dummy sorter (list of frame numbers as
+ * found in the underlying DICOM dataset, and EC_Normal as error code)
+ */
+ virtual void sort(Results& results)
+ {
+ if (m_fg == NULL)
+ {
+ results.errorCode = FG_EC_InvalidData;
+ return;
+ }
+
+ size_t numFrames = m_fg->getNumberOfFrames();
+ if (numFrames == 0)
+ {
+ results.errorCode = FG_EC_NotEnoughItems;
+ return;
+ }
+
+ for (Uint32 count = 0; count < numFrames; count++)
+ {
+ results.frameNumbers.push_back(count);
+ }
+ return;
+ }
+
+};
+
+/** Sorter implementing the FrameSorter interface that sorts frames
+ * by their Image Position (Patient) attribute. The sorting is done
+ * by projecting the Image Position (Patient) on the slice direction
+ * (as defined by the Image Orientation (Patient) attribute).
+ */
+class FrameSorterIPP : public FrameSorter
+{
+public:
+
+ /** Structure that holds a frame for sorting
+ */
+ struct OrderedFrameItem
+ {
+ OrderedFrameItem() :
+ key(),
+ frameId()
+ {}
+
+ /// The key relevant for sorting
+ Float64 key;
+ /// The DICOM frame number
+ Uint32 frameId;
+ /// The frame position as found in Image Position (Patient)
+ ImagePosition framePos;
+ };
+
+
+ /** Default constructor, does nothing
+ */
+ ~FrameSorterIPP(){};
+
+ /** Get description of the sorting algorithm this class uses.
+ * @return Free text description of the sorting algorithm used.
+ */
+ OFString getDescription(){
+ return "Returns frames in the order defined by projecting the ImagePositionPatient on the slice direction.";
+ }
+
+ /** Get the slice direction from Image Orientation (Patient)
+ * @param results The results structure to hold error code in case of failure
+ */
+ void getSliceDirection(Results &results)
+ {
+ OFBool isPerFrame;
+ FGPlaneOrientationPatient *planorfg = OFstatic_cast(FGPlaneOrientationPatient*,
+ m_fg->get(0, DcmFGTypes::EFG_PLANEORIENTPATIENT, isPerFrame));
+ if(!planorfg || isPerFrame){
+ results.errorCode = FG_EC_InvalidData;
+ return;
+ }
+
+ OFVector<Float64> dirX, dirY;
+ OFString orientStr;
+ for(int i=0;i<3;i++){
+ if(planorfg->getImageOrientationPatient(orientStr, i).good()){
+ dirX.push_back(atof(orientStr.c_str()));
+ } else {
+ results.errorCode = FG_EC_InvalidData;
+ break;
+ }
+ }
+ for(int i=3;i<6;i++){
+ if(planorfg->getImageOrientationPatient(orientStr, i).good()){
+ dirY.push_back(atof(orientStr.c_str()));
+ } else {
+ results.errorCode = FG_EC_InvalidData;
+ break;
+ }
+ }
+
+ if(results.errorCode != EC_Normal)
+ return;
+
+ sliceDirection = cross_3d(dirX, dirY);
+ normalize(sliceDirection);
+ }
+
+ /** Performs actual sorting. Sets given results.
+ * @param results The results produced by IPP sorter (list of frame numbers sorted
+ * by Image Position (Patient) projection on slice direction, and EC_Normal
+ * as error code in case of success)
+ */
+ void sort(Results& results)
+ {
+ if(m_fg == NULL){
+ results.errorCode = FG_EC_InvalidData;
+ return;
+ }
+
+ getSliceDirection(results);
+ if(results.errorCode != EC_Normal){
+ return;
+ }
+
+ OFBool isPerFrame;
+ size_t numFrames = m_fg->getNumberOfFrames();
+ if (numFrames > DcmFGTypes::DCMFG_MAX_FRAMES)
+ {
+ results.errorCode = FG_EC_TooManyItems;
+ return;
+ }
+ OrderedFrameItem* orderedFrameItems = new OrderedFrameItem[numFrames];
+
+ for(Uint32 frameId=0;frameId<numFrames;frameId++)
+ {
+ FGPlanePosPatient *planposfg =
+ OFstatic_cast(FGPlanePosPatient*,m_fg->get(frameId, DcmFGTypes::EFG_PLANEPOSPATIENT, isPerFrame));
+
+ if(!planposfg || !isPerFrame){
+ results.errorCode = FG_EC_InvalidData;
+ return;
+ }
+
+ ImagePosition sOrigin;
+ for(int j=0;j<3;j++){
+ OFString planposStr;
+ if(planposfg->getImagePositionPatient(planposStr, j).good()){
+ sOrigin.push_back(atof(planposStr.c_str()));
+ } else {
+ results.errorCode = FG_EC_InvalidData;
+ return;
+ }
+ }
+
+ Float64 dist;
+ dist = dot(sliceDirection, sOrigin);
+ orderedFrameItems[frameId].key = dist;
+ orderedFrameItems[frameId].frameId = frameId;
+ orderedFrameItems[frameId].framePos = sOrigin;
+ }
+
+ qsort(&orderedFrameItems[0], numFrames, sizeof(OrderedFrameItem), &compareIPPKeys);
+
+ for(Uint32 count=0;count<numFrames;count++)
+ {
+ results.frameNumbers.push_back(orderedFrameItems[count].frameId);
+ results.framePositions.push_back(orderedFrameItems[count].framePos);
+ }
+
+ delete [] orderedFrameItems;
+
+ return;
+ }
+
+private:
+
+ /** Calculate the cross product of two 3D vectors.
+ * @param v1 First vector
+ * @param v2 Second vector
+ * @return Cross product vector
+ */
+ OFVector<Float64> cross_3d(OFVector<Float64> v1, OFVector<Float64> v2){
+ OFVector<Float64> result;
+ result.push_back(v1[1]*v2[2]-v1[2]*v2[1]);
+ result.push_back(v1[2]*v2[0]-v1[0]*v2[2]);
+ result.push_back(v1[0]*v2[1]-v1[1]*v2[0]);
+
+ return result;
+ }
+
+ /** Calculate the dot product of two 3D vectors.
+ * @param v1 First vector
+ * @param v2 Second vector
+ * @return Dot product value
+ */
+ Float64 dot(OFVector<Float64> v1, OFVector<Float64> v2){
+ return Float64(v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]);
+ }
+
+ /** Normalize a 3D vector.
+ * @param v The vector to normalize (output parameter)
+ */
+ void normalize(OFVector<Float64> &v){
+ double norm = OFMath::sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
+ v[0] = v[0]/norm;
+ v[1] = v[1]/norm;
+ v[2] = v[2]/norm;
+ }
+
+
+ /** Compare function for qsort to sort OrderedFrameItem by their key.
+ * @param a Pointer to first OrderedFrameItem
+ * @param b Pointer to second OrderedFrameItem
+ * @return Negative value if a < b, zero if a == b, positive if a > b
+ */
+ static int compareIPPKeys(const void *a, const void *b);
+
+ /// The slice direction vector
+ OFVector<Float64> sliceDirection;
+
+};
+
+/** Compare function to compare OrderedFrameItem by their key.
+ * @param a Pointer to first OrderedFrameItem
+ * @param b Pointer to second OrderedFrameItem
+ * @return Returns 1 for a > b, -1 otherwise
+ */
+int FrameSorterIPP::compareIPPKeys(const void *a, const void *b)
+{
+ FrameSorterIPP::OrderedFrameItem *i1, *i2;
+ i1 = (FrameSorterIPP::OrderedFrameItem*) a;
+ i2 = (FrameSorterIPP::OrderedFrameItem*) b;
+ if(i1->key > i2->key)
+ return 1;
+ else
+ return -1;
+}
+
+#endif // FRAMESORTHER_H
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../include/dcmtk/dcmfg/concatenationcreator.h \
- ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgtypes.h
+ ../include/dcmtk/dcmfg/fgdefine.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../include/dcmtk/dcmfg/fgtypes.h
concatenationloader.o: concatenationloader.cc \
../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
- ../include/dcmtk/dcmfg/fgderimg.h ../include/dcmtk/dcmfg/fgbase.h \
- ../include/dcmtk/dcmfg/fgtypes.h ../include/dcmtk/dcmfg/fgdefine.h \
+ ../include/dcmtk/dcmfg/fgderimg.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \
+ ../include/dcmtk/dcmfg/fgdefine.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../include/dcmtk/dcmfg/fgctgeometry.h \
../include/dcmtk/dcmfg/fgcttabledynamics.h \
../include/dcmtk/dcmfg/fgctxraydetails.h \
../include/dcmtk/dcmfg/fgderimg.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
../include/dcmtk/dcmfg/fgfact.h ../include/dcmtk/dcmfg/fgfracon.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
../include/dcmtk/dcmfg/fgtemporalposition.h \
../include/dcmtk/dcmfg/fgusimagedescription.h \
../../dcmiod/include/dcmtk/dcmiod/iodutil.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h
fgfracon.o: fgfracon.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h
fgframeanatomy.o: fgframeanatomy.cc \
../../config/include/dcmtk/config/osconfig.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../dcmiod/include/dcmtk/dcmiod/iodutil.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrss.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../include/dcmtk/dcmfg/fgdefine.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../dcmiod/include/dcmtk/dcmiod/iodutil.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
- ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def
/*
*
- * Copyright (C) 2019-2024, Open Connections GmbH
+ * Copyright (C) 2019-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmfg/concatenationcreator.h"
#include "dcmtk/dcmfg/fgtypes.h"
-
// Maximum number of instances that make up a Concatenation
const Uint16 ConcatenationCreator::m_MAX_INSTANCES_PER_CONCATENATION = 65535;
if (m_cfgTransferOwnership)
{
delete m_srcDataset;
- delete[] m_srcPixelData;
}
+ // knows whether to free pixel data or not
+ delete m_srcPixelData;
}
OFCondition ConcatenationCreator::setCfgInput(DcmItem* srcDataset, OFBool transferOwnership)
{
// Check pixel data exists and is in native format (i.e. uncompressed)
- DcmElement* elem = NULL;
- srcDataset->findAndGetElement(DCM_PixelData, elem);
- if (!elem)
- return FG_EC_PixelDataMissing;
- DcmPixelData* pixDataElem = OFstatic_cast(DcmPixelData*, elem);
- if (!pixDataElem)
- return FG_EC_PixelDataMissing;
- if (!pixDataElem->canWriteXfer(EXS_LittleEndianExplicit, EXS_LittleEndianExplicit /* ignored */))
- return EC_UnsupportedEncoding;
- OFCondition result = pixDataElem->getUint8Array(m_srcPixelData);
- if (!m_srcPixelData || result.bad())
- return FG_EC_PixelDataMissing;
+ OFCondition result = initSrcPixelData(srcDataset, transferOwnership);
+ if (result.good())
+ {
+ m_srcDataset = srcDataset;
+ m_cfgTransferOwnership = transferOwnership;
+ }
- m_srcDataset = srcDataset;
+ return result;
+}
+OFCondition ConcatenationCreator::setCfgInput(DcmItem* srcDataset,
+ Uint8* pixelData,
+ size_t pixelDataLength,
+ OFBool transferOwnership)
+{
+ // Check input parameters
+ if (!pixelData)
+ return FG_EC_PixelDataMissing;
+
+ m_srcDataset = srcDataset;
+ delete m_srcPixelData;
+ m_srcPixelData = NULL;
+ m_srcPixelData = new DcmIODTypes::Frame<Uint8>(pixelData, pixelDataLength);
+ m_srcPixelData->setReleaseMemory(transferOwnership);
m_cfgTransferOwnership = transferOwnership;
// All fine
return EC_Normal;
}
+
OFCondition ConcatenationCreator::setCfgInput(DcmItem* srcDataset,
- Uint8* pixelData,
- size_t /* pixelDataLength */,
+ Uint16* pixelData,
+ size_t pixelDataLength,
OFBool transferOwnership)
{
// Check input parameters
return FG_EC_PixelDataMissing;
m_srcDataset = srcDataset;
- m_srcPixelData = pixelData;
+ delete m_srcPixelData;
+ m_srcPixelData = NULL;
+ m_srcPixelData = new DcmIODTypes::Frame<Uint16>(pixelData, pixelDataLength);
+ m_srcPixelData->setReleaseMemory(transferOwnership);
m_cfgTransferOwnership = transferOwnership;
// All fine
return EC_Normal;
}
+
OFCondition ConcatenationCreator::setCfgFramesPerInstance(Uint32 numFramesPerInstance)
{
m_cfgNumFramesPerInstance = numFramesPerInstance;
{
return EC_MemoryExhausted;
}
+ // Setting VR is necessary if Pixel Data is actually 16 bit
dstPixelData->setVR(m_VRPixelData);
size_t srcPos = (m_numBitsFrame * m_currentSrcFrame) / 8;
- memcpy(dstData, &m_srcPixelData[srcPos], numTotalBytesInstance);
+ memcpy(dstData, &(OFstatic_cast(Uint8*, m_srcPixelData->getPixelData())[srcPos]), numTotalBytesInstance);
result = dstDataset.insert(dstPixelData.release());
if (result.good())
{
m_configured = OFTrue;
return result;
}
+
+
+OFCondition ConcatenationCreator::initSrcPixelData(DcmItem* srcDataset, OFBool transferOwnership)
+{
+ // Check pixel data exists and is in native format (i.e. uncompressed)
+ DcmElement* elem = NULL;
+ srcDataset->findAndGetElement(DCM_PixelData, elem);
+ if (!elem)
+ return FG_EC_PixelDataMissing;
+ DcmPixelData* pixDataElem = OFstatic_cast(DcmPixelData*, elem);
+ if (!pixDataElem)
+ return FG_EC_PixelDataMissing;
+ if (!pixDataElem->canWriteXfer(EXS_LittleEndianExplicit, EXS_LittleEndianExplicit /* ignored */))
+ return EC_UnsupportedEncoding;
+ size_t pixDataLength = pixDataElem->getLength();
+ Uint16 bitsAllocated = 0;
+ srcDataset->findAndGetUint16(DCM_BitsAllocated, bitsAllocated);
+ if ((bitsAllocated != 8) && (bitsAllocated != 16) && (bitsAllocated != 1))
+ return FG_EC_UnsupportedPixelDataLayout;
+
+ OFCondition result;
+ if (bitsAllocated <= 8)
+ {
+ Uint8 *pixelData = NULL;
+ result = pixDataElem->getUint8Array(pixelData);
+ if (!pixelData || result.bad())
+ return FG_EC_PixelDataMissing;
+ m_srcPixelData = new DcmIODTypes::Frame<Uint8>(pixelData, pixDataLength);
+ }
+ else // bits allocated = 16
+ {
+ Uint16 *pixelData = NULL;
+ result = pixDataElem->getUint16Array(pixelData);
+ if (!pixelData || result.bad())
+ return FG_EC_PixelDataMissing;
+ m_srcPixelData = new DcmIODTypes::Frame<Uint16>(pixelData, pixDataLength);
+ }
+ m_srcPixelData->setReleaseMemory(transferOwnership);
+ return EC_Normal;
+
+
+}
/*
*
- * Copyright (C) 2019-2024, Open Connections GmbH
+ * Copyright (C) 2019-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
}
OFCondition
-ConcatenationLoader::load(const OFString& concatenationUID, DcmDataset* dataset, OFVector<DcmIODTypes::Frame*>& frames)
+ConcatenationLoader::load(const OFString& concatenationUID, DcmDataset* dataset, OFVector<DcmIODTypes::FrameBase*>& frames)
{
if (dataset == NULL)
return EC_IllegalParameter;
OFCondition ConcatenationLoader::extractFrames(DcmItem& item, Info& info, const Uint32 numFrames)
{
- const Uint8* pixData = NULL;
- OFCondition result = item.findAndGetUint8Array(DCM_PixelData, pixData);
- if (result.good() && pixData)
+ const Uint8* pixData8 = NULL;
+ const Uint16* pixData16 = NULL;
+ OFCondition result;
+ if (info.m_BitsAlloc <= 8)
+ {
+ result = item.findAndGetUint8Array(DCM_PixelData, pixData8);
+ }
+ else if (info.m_BitsAlloc == 16)
+ {
+ result = item.findAndGetUint16Array(DCM_PixelData, pixData16);
+ }
+ else
+ {
+ DCMFG_ERROR("Bits Allocated=" << info.m_BitsAlloc << " not supported, must be 1, 8 or 16");
+ return FG_EC_UnsupportedPixelDataLayout;
+ }
+ if (result.good() && (pixData8 || pixData16))
{
size_t bytesPerFrame = 0;
result = computeBytesPerFrame(info.m_Rows, info.m_Cols, info.m_BitsAlloc, bytesPerFrame);
if (result.good())
{
- const Uint8* ptr = pixData;
for (Uint32 f = 0; f < numFrames; f++)
{
- DcmIODTypes::Frame* frame = new DcmIODTypes::Frame();
- if (frame)
+ DcmIODTypes::FrameBase* frame = NULL;
+ if (info.m_BitsAlloc <= 8) // 8 or 1
{
- frame->length = bytesPerFrame;
- frame->pixData = new Uint8[frame->length];
- if (frame->pixData)
+ frame = new DcmIODTypes::Frame<Uint8>(bytesPerFrame);
+ if (frame && frame->getPixelData())
{
- memcpy(frame->pixData, ptr, frame->length);
- ptr += frame->length;
- m_Frames.push_back(frame);
+ const Uint8* ptr = pixData8 + f * frame->getLengthInBytes();
+ memcpy(frame->getPixelData(), ptr, frame->getLengthInBytes());
}
- else
+ }
+ else if (info.m_BitsAlloc == 16)
+ {
+ frame = new DcmIODTypes::Frame<Uint16>(bytesPerFrame / 2);
+ if (frame && frame->getPixelData())
{
- result = EC_MemoryExhausted;
+ // getLength() returns size in bytes, so divide by 2 since we advance by word
+ const Uint16* ptr = pixData16 + f * frame->getLengthInBytes() / 2;
+ // memcpy expects number of bytes to copy
+ memcpy(frame->getPixelData(), ptr, frame->getLengthInBytes());
}
}
+ if (frame)
+ {
+ m_Frames.push_back(frame);
+ }
else
{
result = EC_MemoryExhausted;
// This is only different if bits allocated equals 1, which can happen
// for binary segmentations or black and white secondary capture objects
// (second SC generation).
- // Other values than Bits Allocated 16 or 8 are not supported.
+ // Other values than Bits Allocated 16, 8 or 1 are not supported.
bytes_per_frame = bitsAlloc * cols * rows;
if ((bitsAlloc == 16) || (bitsAlloc == 8))
{
/*
*
- * Copyright (C) 2015-2019, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
}
}
+size_t FunctionalGroups::size() const
+{
+ return m_groups.size();
+}
+
FGBase* FunctionalGroups::find(const DcmFGTypes::E_FGType fgType)
{
FGBase* group = NULL;
/*
*
- * Copyright (C) 2016-2024, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
SourceImageItem::SourceImageItem()
: m_PurposeOfReferenceCode()
, m_ImageSOPInstanceReference()
+ , m_SpatialLocationsPreserved(DCM_SpatialLocationsPreserved)
{
}
{
m_PurposeOfReferenceCode = rhs.m_PurposeOfReferenceCode;
m_ImageSOPInstanceReference = rhs.m_ImageSOPInstanceReference;
+ m_SpatialLocationsPreserved = rhs.m_SpatialLocationsPreserved;
return *this;
}
{
m_PurposeOfReferenceCode.clearData();
m_ImageSOPInstanceReference.clear();
+ m_SpatialLocationsPreserved.clear();
}
OFCondition SourceImageItem::check() const
{
result = this->m_ImageSOPInstanceReference.compare(rhs.m_ImageSOPInstanceReference);
}
+ if (result != 0)
+ {
+ result = this->m_SpatialLocationsPreserved.compare(rhs.m_SpatialLocationsPreserved);
+ }
return result;
}
return m_ImageSOPInstanceReference;
}
+OFCondition SourceImageItem::getSpatialLocationsPreserved(OFString& value, const long signed int pos) const
+{
+ return DcmIODUtil::getStringValueFromElement(m_SpatialLocationsPreserved, value, pos);
+}
+
+OFCondition SourceImageItem::setSpatialLocationsPreserved(const OFString& value, const OFBool checkValue)
+{
+ OFCondition result = (checkValue) ? DcmCodeString::checkStringValue(value, "1") : EC_Normal;
+ if (result.good())
+ result = m_SpatialLocationsPreserved.putOFStringArray(value);
+ return result;
+}
+
+
OFCondition SourceImageItem::read(DcmItem& itemOfSourceImageSequence, const OFBool clearOldData)
{
/* Re-initialize object */
if (clearOldData)
clearData();
+ /* Spatial Locations Preserved */
+ DcmIODUtil::getAndCheckElementFromDataset(itemOfSourceImageSequence, m_SpatialLocationsPreserved, "1", "3", "DerivationImageMacro");
+
/* Read Purpose of Reference Code Sequence */
DcmIODUtil::readSingleItem<CodeSequenceMacro>(itemOfSourceImageSequence,
DCM_PurposeOfReferenceCodeSequence,
m_ImageSOPInstanceReference.write(itemOfSourceImageSequence);
}
+ /** Currently only writes Spatial Locations Preserved */
+ if (result.good())
+ {
+ result = DcmIODUtil::copyElementToDataset(
+ result, itemOfSourceImageSequence, m_SpatialLocationsPreserved, "1" /* vm */, "3" /*requirement type*/, "DerivationImageMacro");
+ }
+
return result;
}
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmfg/fgfact.h" // for creating new functional groups
#include "dcmtk/dcmfg/fginterface.h"
#include "dcmtk/ofstd/ofmap.h"
+#include "dcmtk/ofstd/ofthread.h"
#include "dcmtk/ofstd/ofmem.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcsequen.h"
+
+// ---------------------------------- ThreadedFGWriter ----------------------------------
+// This class is used to write functional groups in parallel for a group of frames, each.
+FGInterface::ThreadedFGWriter::ThreadedFGWriter()
+ : OFThread()
+ , m_frameGroups(OFnullptr)
+ , m_perFrameResultItems(OFnullptr)
+ , m_startFrame(0)
+ , m_endFrame(0)
+ , m_errorMutex(OFnullptr)
+{
+}
+
+void FGInterface::ThreadedFGWriter::init(OFVector<OFPair<Uint32, FunctionalGroups*> >* frameGroups,
+ OFVector<DcmItem*>* perFrameResultItems,
+ OFMutex* perFrameResultItemsMutex,
+ const Uint32 startFrame,
+ const Uint32 endFrame,
+ OFConditionConst* errorOccurred,
+ OFMutex* errorMutex)
+{
+ // Store the parameters in member variables
+ m_frameGroups = frameGroups;
+ m_perFrameResultItems = perFrameResultItems;
+ m_perFrameResultItemsMutex = perFrameResultItemsMutex;
+ m_startFrame = startFrame;
+ m_endFrame = endFrame;
+ m_errorOccurred = errorOccurred;
+ m_errorMutex = errorMutex;
+}
+
+
+FGInterface::ThreadedFGWriter::~ThreadedFGWriter()
+{
+ // Nothing to do here
+}
+
+void FGInterface::ThreadedFGWriter::run()
+{
+ if (!m_frameGroups || !m_perFrameResultItems)
+ {
+ DCMFG_ERROR("ThreadedFGWriter: Not properly initialized, cannot run.");
+ m_errorMutex->lock();
+ *m_errorOccurred = FG_EC_ParallelProcessingFailed;
+ m_errorMutex->unlock();
+ return;
+ }
+
+ // Iterate over all frames and write the functional groups
+ for (Uint32 idx = m_startFrame; idx < m_endFrame; ++idx)
+ {
+ Uint32 frameNo = m_frameGroups->at(idx).first;
+ FunctionalGroups* fgPtr = m_frameGroups->at(idx).second;
+ OFunique_ptr<DcmItem> perFrameItem(new DcmItem());
+
+ FunctionalGroups::iterator groupIt = fgPtr->begin();
+ while ((groupIt != fgPtr->end()))
+ {
+ m_errorMutex->lock();
+ if (*m_errorOccurred != EC_Normal)
+ {
+ m_errorMutex->unlock();
+ DCMFG_ERROR("Error occurred, stopping further processing.");
+ return;
+ }
+ m_errorMutex->unlock();
+ DCMFG_DEBUG("Writing per-frame group: "
+ << DcmFGTypes::FGType2OFString((*groupIt).second->getType())
+ << " for frame #" << frameNo);
+ OFCondition result = (*groupIt).second->write(*perFrameItem);
+ groupIt++;
+ if (result.bad())
+ {
+ DCMFG_ERROR("Error writing functional group for frame #" << frameNo << ": " << result.text());
+ m_errorMutex->lock();
+ *m_errorOccurred = result.condition(); // Store the error
+ m_errorMutex->unlock();
+ return;
+ }
+ }
+ // Lock the mutex before modifying shared data
+ m_perFrameResultItemsMutex->lock();
+ (*m_perFrameResultItems)[idx] = perFrameItem.release();
+ m_perFrameResultItemsMutex->unlock();
+ }
+}
+
+
+// ---------------------------------- ThreadedFGWReader ----------------------------------
+
+FGInterface::ThreadedFGReader::ThreadedFGReader()
+ : OFThread()
+ , m_perFrameItems(OFnullptr)
+ , m_frameResultGroups(OFnullptr)
+ , m_frameResultGroupsMutex(OFnullptr)
+ , m_startFrame(0)
+ , m_endFrame(0)
+ , m_errorMutex(OFnullptr)
+ , m_errorOccurred(OFnullptr)
+{
+}
+
+
+void FGInterface::ThreadedFGReader::init(OFVector<DcmItem*>* perFrameItems,
+ OFMutex* perFrameItemsMutex,
+ PerFrameGroups* frameResultGroups,
+ OFMutex* frameResultGroupsMutex,
+ Uint32 startFrame,
+ Uint32 endFrame,
+ OFMutex* errorMutex,
+ OFConditionConst* errorOccurred,
+ FGInterface* fgInterfacePtr)
+{
+ m_perFrameItems = perFrameItems;
+ m_perFrameItemsMutex = perFrameItemsMutex;
+ m_frameResultGroups = frameResultGroups;
+ m_frameResultGroupsMutex = frameResultGroupsMutex;
+ m_startFrame = startFrame;
+ m_endFrame = endFrame;
+ m_errorMutex = errorMutex;
+ m_errorOccurred = errorOccurred;
+ m_fgInterfacePtr = fgInterfacePtr;
+}
+
+FGInterface::ThreadedFGReader::~ThreadedFGReader()
+{
+ // Nothing to do here
+}
+
+
+void FGInterface::ThreadedFGReader::run()
+{
+ if (!m_perFrameItems || !m_frameResultGroups)
+ {
+ DCMFG_ERROR("ThreadedFGReader: Not properly initialized, cannot run.");
+ m_errorMutex->lock();
+ *m_errorOccurred = FG_EC_ParallelProcessingFailed;
+ m_errorMutex->unlock();
+ return;
+ }
+
+ // Iterate over all frames and read the functional groups
+ for (Uint32 idx = m_startFrame; idx < m_endFrame; ++idx)
+ {
+ Uint32 frameNo = idx;
+ // No need to lock for reading from m_perFrameItems, as each thread only reads its assigned range
+ if (frameNo >= m_perFrameItems->size())
+ {
+ DCMFG_ERROR("Frame index " << frameNo << " out of bounds for per-frame items vector");
+ m_errorMutex->lock();
+ *m_errorOccurred = FG_EC_ParallelProcessingFailed;
+ m_errorMutex->unlock();
+ return;
+ }
+ DcmItem* perFrameItem = (*m_perFrameItems)[frameNo];
+ if (!perFrameItem)
+ {
+ DCMFG_ERROR("No per-frame item found for frame #" << frameNo);
+ m_errorMutex->lock();
+ *m_errorOccurred = FG_EC_ParallelProcessingFailed; // Store the error
+ m_errorMutex->unlock();
+ return;
+ }
+
+ DCMFG_DEBUG("Reading per-frame groups for frame #" << frameNo);
+ // Create a new FunctionalGroups object to store the read groups
+ OFunique_ptr<FunctionalGroups> groupsOneFrame(new FunctionalGroups());
+ if (!groupsOneFrame)
+ {
+ DCMFG_ERROR("Memory exhausted while creating FunctionalGroups object for frame #" << frameNo);
+ m_errorMutex->lock();
+ *m_errorOccurred = EC_MemoryExhausted; // Store the error
+ m_errorMutex->unlock();
+ return;
+ }
+ // Read the functional groups from the per-frame item
+ // Remove parent item since otherwise the code will try to access the parent item
+ // to find the Specific Character Set, and this will crash if multiple threads
+ // try to access the same parent item.
+ DcmSequenceOfItems* perFrameFGSeq = OFstatic_cast(DcmSequenceOfItems*, perFrameItem->getParent());
+ perFrameItem->setParent(OFnullptr);
+ OFCondition result = m_fgInterfacePtr->readSingleFG(*perFrameItem, *groupsOneFrame);
+ perFrameItem->setParent(perFrameFGSeq); // Restore parent item
+ if (result.bad())
+ {
+ DCMFG_ERROR("Error reading functional groups for frame #" << frameNo << ": " << result.text());
+ m_errorMutex->lock();
+ *m_errorOccurred = result.condition(); // Store the error
+ m_errorMutex->unlock();
+ return;
+ }
+ // Lock the mutex before modifying shared data
+ m_frameResultGroupsMutex->lock();
+ // cast is safe since we check earlier that it is not
+ // larger than DcmFGTypes::DCMFG_MAX_FRAMES (2^32-1)
+ m_frameResultGroups->insert(OFMake_pair(frameNo, groupsOneFrame.release()));
+ m_frameResultGroupsMutex->unlock();
+ DCMFG_DEBUG("Finished reading functional groups for frame #" << frameNo);
+ }
+}
+
+
+
+// ----------------------------------- FGInterface -----------------------------------
+
FGInterface::FGInterface()
: m_shared()
, m_perFrame()
, m_checkOnWrite(OFTrue)
+ , m_numThreads(1) // Default to 1 thread
{
}
size_t numFrames = perFrame->card();
if (numFrames == 0)
{
- DCMFG_WARN("No Item in Shared Functional Group Sequence but exactly one or more expected");
+ DCMFG_WARN("No Item in Per-Frame Functional Group Sequence but exactly one or more expected");
return FG_EC_NoPerFrameFG;
}
+ if (numFrames > DcmFGTypes::DCMFG_MAX_FRAMES)
+ {
+ DCMFG_ERROR("Too many items in Per-Frame Functional Group Sequence: " << numFrames
+ << ", maximum is " << DcmFGTypes::DCMFG_MAX_FRAMES);
+ return FG_EC_TooManyItems;
+ }
+ // We want to either read sequentially or in parallel, depending on the number of threads.
+ // Cast is safe since e checked range above.
+ Uint32 threadsUsed = findAdequateNumberOfThreads(OFstatic_cast(Uint32, numFrames), m_numThreads);
+ if (threadsUsed > 1)
+ {
+ result = readPerFrameFGParallel(*perFrame, m_numThreads);
+ }
+ else
+ {
+ result = readPerFrameFGSequential(*perFrame);
+ }
+ return EC_Normal; // for now we always return EC_Normal...
+}
+
+
+OFCondition FGInterface::readPerFrameFGSequential(DcmSequenceOfItems& perFrameFGSeq)
+{
/* Read functional groups for each item (one per frame) */
- DcmItem* oneFrameItem = OFstatic_cast(DcmItem*, perFrame->nextInContainer(NULL));
+ OFCondition result;
+ DcmItem* oneFrameItem = OFstatic_cast(DcmItem*, perFrameFGSeq.nextInContainer(NULL));
Uint32 count = 0;
while (oneFrameItem != NULL)
{
DCMFG_ERROR("Could not read functional groups for frame #" << count << ": " << result.text());
}
}
- oneFrameItem = OFstatic_cast(DcmItem*, perFrame->nextInContainer(oneFrameItem));
+ oneFrameItem = OFstatic_cast(DcmItem*, perFrameFGSeq.nextInContainer(oneFrameItem));
count++;
}
return EC_Normal; // for now we always return EC_Normal...
}
+
+OFCondition FGInterface::readPerFrameFGParallel(DcmSequenceOfItems& perFrameFGSeq, const Uint32 numThreads)
+{
+ DCMFG_DEBUG("Reading per-frame functional groups in parallel using " << numThreads << " threads");
+ // Read functional groups for each item (one per frame)
+ OFCondition result;
+ size_t numFrames = perFrameFGSeq.card();
+
+ // Create a vector to hold the functional groups for each frame and protect it with a mutex
+ PerFrameGroups& perFrameResultGroups = m_perFrame;
+ OFMutex perFrameResultGroupsMutex;
+
+ // Create a vector to hold the results of all threads, protected by a mutex
+ OFMutex perFrameInputMutex;
+ OFVector<DcmItem*> perFrameInputItems(numFrames, NULL);
+ // Fill the vector with items from the sequence
+ DcmItem* oneFrameItem = OFstatic_cast(DcmItem*, perFrameFGSeq.nextInContainer(NULL));
+ size_t count = 0;
+ while (oneFrameItem != NULL)
+ {
+ // Store the item in the vector
+ perFrameInputItems[count] = oneFrameItem;
+ oneFrameItem = OFstatic_cast(DcmItem*, perFrameFGSeq.nextInContainer(oneFrameItem));
+ count++;
+ }
+
+ // Create a mutex for error handling
+ OFConditionConst errorOccurred = EC_Normal;
+ OFMutex errorMutex;
+
+ // Create and start threads
+ OFVector<ThreadedFGReader*> threads(numThreads);
+ // Range check on numFrames has been performed earlier so computation should be safe
+ Uint32 framesPerThread = OFstatic_cast(Uint32, (numFrames + numThreads - 1) / numThreads);
+ for (Uint32 i = 0; i < numThreads; ++i)
+ {
+ threads[i] = new ThreadedFGReader();
+ Uint32 startFrame = i * framesPerThread;
+ // numFrame is range-checked earlier
+ Uint32 endFrame = (startFrame + framesPerThread < numFrames) ? startFrame + framesPerThread : OFstatic_cast(Uint32, numFrames);
+
+ threads[i]->init(&perFrameInputItems, &perFrameInputMutex,
+ &perFrameResultGroups, &perFrameResultGroupsMutex,
+ startFrame,
+ endFrame,
+ &errorMutex, &errorOccurred, this);
+ }
+ // Start all threads
+ for (Uint32 i = 0; i < numThreads; ++i)
+ {
+ threads[i]->start();
+ }
+
+ // Wait for all threads to finish
+ for (Uint32 i = 0; i < numThreads; ++i)
+ {
+ threads[i]->join();
+ delete threads[i];
+ threads[i] = NULL;
+ }
+
+ // Check if any thread encountered an error
+ if (errorOccurred != EC_Normal)
+ {
+ DCMFG_ERROR("Error occurred while reading functional groups in parallel: " << OFCondition(errorOccurred).text());
+ return errorOccurred;
+ }
+
+ // Store the results in m_perFrame
+ return EC_Normal;
+}
+
+
+
OFCondition FGInterface::readSingleFG(DcmItem& fgItem, FunctionalGroups& groups)
{
OFCondition result;
// Write shared functional Groups
OFCondition result = writeSharedFG(dataset);
+ DcmItem* seqItem;
+ dataset.findAndGetSequenceItem(DCM_SharedFunctionalGroupsSequence, seqItem);
// Write per frame functional groups
if (result.good())
result = writePerFrameFG(dataset);
return m_checkOnWrite;
}
+void FGInterface::setUseThreads(const Uint32 numThreads)
+{
+ if (numThreads > 0)
+ {
+ m_numThreads = numThreads;
+ }
+ else
+ {
+ m_numThreads = 1; // Fallback to single-threaded mode
+ }
+}
+
+Uint32 FGInterface::getUseThreads() const
+{
+ return m_numThreads;
+}
+
FunctionalGroups* FGInterface::getOrCreatePerFrameGroups(const Uint32 frameNo)
{
OFMap<Uint32, FunctionalGroups*>::iterator it = m_perFrame.find(frameNo);
return fg;
}
+
OFCondition FGInterface::writePerFrameFG(DcmItem& dataset)
+{
+ OFCondition result;
+
+ DCMFG_DEBUG("Writing per-frame functional groups");
+ result = dataset.insertEmptyElement(DCM_PerFrameFunctionalGroupsSequence, OFTrue); // start with empty sequence
+ if (result.bad())
+ {
+ DCMFG_ERROR("Could not create Per-frame Functional Groups Sequence");
+ return result;
+ }
+
+ /* Iterate over frames */
+ size_t numFrames = m_perFrame.size();
+ if (numFrames > DcmFGTypes::DCMFG_MAX_FRAMES)
+ {
+ DCMFG_ERROR("Too many frames in Per-frame Functional Groups: " << numFrames
+ << ", maximum is " << DcmFGTypes::DCMFG_MAX_FRAMES);
+ return FG_EC_TooManyItems;
+ }
+
+ // Use parallel processing for writing functional groups, if desired and adequate.
+ // Cast is safe since we checked range above.
+ Uint32 threadsUsed = findAdequateNumberOfThreads(OFstatic_cast(Uint32, numFrames), m_numThreads);
+ if (threadsUsed > 1)
+ {
+ result = writePerFrameFGParallel(dataset, m_numThreads);
+ }
+ else
+ {
+ // Fallback to sequential processing for small datasets or single-threaded environment
+ result = writePerFrameFGSequential(dataset);
+ }
+
+ return result;
+}
+
+OFCondition FGInterface::writePerFrameFGSequential(DcmItem& dataset)
{
DCMFG_DEBUG("Writing per-frame functional groups");
OFCondition result
return result;
}
+
+OFCondition FGInterface::writePerFrameFGParallel(DcmItem& dataset, const Uint32 numThreads)
+{
+ DCMFG_DEBUG("Writing per-frame functional groups in parallel using " << numThreads << " threads");
+ OFConditionConst errorOccurred(EC_Normal);
+ OFMutex errorMutex;
+ OFMutex perFrameItemsMutex;
+
+ // Prepare a vector of frame numbers and their corresponding FunctionalGroups pointers.
+ // We need this to distribute the work across threads. Using the OFMap directly in threads
+ // could lead to data races and inconsistencies since each thread would invalidate the iterators
+ // being used in the other threads.
+ OFVector<OFPair<Uint32, FunctionalGroups*> > frameGroups;
+ frameGroups.reserve(m_perFrame.size());
+ for (OFMap<Uint32, FunctionalGroups*>::iterator it = m_perFrame.begin(); it != m_perFrame.end(); ++it)
+ {
+ frameGroups.push_back(OFMake_pair((*it).first, (*it).second));
+ }
+ // We check earlier that number of frames is not larger than max allowed
+ Uint32 numFrames = OFstatic_cast(Uint32, frameGroups.size());
+
+ // Prepare output vector for per-frame items
+ OFVector<DcmItem*> perFrameItems(numFrames, NULL);
+
+ // Thread pool
+ OFVector<ThreadedFGWriter*> threads;
+ threads.reserve(numThreads);
+
+ Uint32 framesPerThread = (numFrames + numThreads - 1) / numThreads;
+
+ for (Uint32 threadIndex = 0; threadIndex < numThreads; ++threadIndex)
+ {
+ Uint32 startFrame = threadIndex * framesPerThread;
+ Uint32 endFrame = (startFrame + framesPerThread < numFrames) ? startFrame + framesPerThread : numFrames;
+
+ ThreadedFGWriter* writer = new ThreadedFGWriter();
+ writer->init(&frameGroups, &perFrameItems, &perFrameItemsMutex, startFrame, endFrame, &errorOccurred, &errorMutex);
+ threads.push_back(writer);
+ writer->start(); // Start the thread
+ }
+
+ // Wait for all threads to complete
+ OFVector<ThreadedFGWriter*>::iterator thread = threads.begin();
+ while (thread != threads.end())
+ {
+ (*thread)->join();
+ delete (*thread); // Clean up the thread object
+ thread++;
+ }
+ threads.clear();
+
+ if (errorOccurred == EC_Normal)
+ {
+ DCMFG_DEBUG("All threads completed successfully, inserting per-frame items into the dataset");
+ }
+ else
+ {
+ DCMFG_ERROR("Error occurred in one or more threads: " << OFCondition(errorOccurred).text());
+ return OFCondition(errorOccurred);
+ }
+ // insert all per-frame items into the dataset
+ OFCondition result;
+ for (size_t idx = 0; idx < perFrameItems.size(); ++idx)
+ {
+ DcmItem* perFrameItem = perFrameItems[idx];
+ Uint32 frameNo = frameGroups[idx].first;
+ if (perFrameItem != NULL)
+ {
+ DCMFG_DEBUG("Inserting per-frame item for frame #" << frameNo);
+ result = dataset.insertSequenceItem(DCM_PerFrameFunctionalGroupsSequence, perFrameItem, OFstatic_cast(long, frameNo));
+ if (result.bad())
+ {
+ DCMFG_ERROR("Error inserting per-frame item for frame #" << frameNo << ": " << result.text());
+ break;
+ }
+ }
+ else
+ {
+ DCMFG_ERROR("Per-frame item for frame #" << frameNo << " is NULL, cannot insert into dataset");
+ }
+ }
+ return result; // Return the result of the last insertion
+}
+
+
OFCondition FGInterface::writeSharedFG(DcmItem& dataset)
{
DCMFG_DEBUG("Writing shared functional groups");
DCMFG_ERROR("Could not create Shared Functional Groups Sequence with single item");
return result;
}
-
+ DCMFG_DEBUG("Writing " << m_shared.size() << " shared functional groups to item");
FunctionalGroups::iterator it = m_shared.begin();
FunctionalGroups::iterator end = m_shared.end();
while ((it != end) && result.good())
{
if (replaceExisting)
{
- DCMFG_DEBUG("Replacing per-frame FG for frame: " << frameNo << ", type: "
- << DcmFGTypes::FGType2OFString(group->getType()));
deletePerFrame(frameNo, group->getType());
}
else
return result;
}
+
+Uint32 FGInterface::findAdequateNumberOfThreads(const Uint32 numFrames, const Uint32 userThreadSetting)
+{
+ // If no threads are requested, we use one thread
+ if (userThreadSetting == 0)
+ {
+ DCMFG_DEBUG("No threads requested, using 1 thread by default.");
+ return 1;
+ }
+ // We should have at least 10 frames per thread, lower number of threads so
+ // that every thread has at least 10 frames to process.
+ Uint32 framesPerThread = numFrames / userThreadSetting;
+ if (framesPerThread < 10)
+ {
+ DCMFG_DEBUG("Requested number of threads (" << userThreadSetting
+ << ") is too high for the number of frames (" << numFrames
+ << "), reducing to a minimum of 10 frames per thread.");
+ // If the user requested more threads than we can use, we limit the number of threads
+ // to the number of frames divided by 10.
+ Uint32 numThreads = numFrames / 10;
+ if (numThreads < 1)
+ {
+ numThreads = 1; // At least one thread is required
+ }
+ return numThreads;
+ }
+ DCMFG_DEBUG("Using " << userThreadSetting << " threads for " << numFrames << " frames");
+
+ // If we have enough frames per thread, we can use the user setting
+ DCMFG_DEBUG("Using user-defined number of threads: " << userThreadSetting);
+ return userThreadSetting;
+}
+
+
FGBase* FGInterface::get(const Uint32 frameNo, const DcmFGTypes::E_FGType fgType, OFBool& isPerFrame)
{
FGBase* group = m_shared.find(fgType);
for (size_t frameCount = 0; frameCount < numFrames; frameCount++)
{
DCMFG_TRACE("Checking frame " << frameCount << "...");
- // Every frame requires the FrameContent functional group, check "en passant"
+ // Most IODS require the FrameContent functional group, check "en passant"
OFBool foundFrameContent = OFFalse;
OFMap<Uint32, FunctionalGroups*>::iterator frameFG = m_perFrame.begin();
OFMap<Uint32, FunctionalGroups*>::iterator end = m_perFrame.end();
}
if (!foundFrameContent)
{
- DCMFG_ERROR("Frame Content Functional group missing for frame #" << frameCount);
- numErrors++;
+ // TODO: This is an error for some IODs but not all (it used to be in earlier editions of the standard)
+ DCMFG_WARN("Frame Content Functional group missing for frame #" << frameCount);
+ // numErrors++;
}
}
/*
*
- * Copyright (C) 2015-2019, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
OFCondition FGSegmentation::setReferencedSegmentNumber(const Uint16& segmentNumber)
{
+ if (segmentNumber == 0)
+ {
+ // Segment numbers start at 1, so 0 is invalid
+ DCMFG_ERROR("Segment Number must not be 0");
+ return FG_EC_InvalidData;
+ }
return m_ReferencedSegmentNumber.putUint16(segmentNumber);
}
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
makeOFConditionConst(FG_EC_InconsistentConcatenationData, OFM_dcmfg, 19, OF_error, "Inconsistent Concatenation Data");
makeOFConditionConst(FG_EC_ConcatenationComplete, OFM_dcmfg, 20, OF_error, "Concatenation Complete - no more data");
makeOFConditionConst(FG_EC_UnsupportedPixelDataLayout, OFM_dcmfg, 21, OF_error, "Unsupported pixel data layout");
+makeOFConditionConst(FG_EC_ParallelProcessingFailed, OFM_dcmfg, 22, OF_error, "Parallel processing failed");
OFString DcmFGTypes::FGType2OFString(const DcmFGTypes::E_FGType fgType)
{
)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(dcmfg_tests dcmfg dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(dcmfg_tests dcmfg)
# This macro parses tests.cc and registers all tests
DCMTK_ADD_TESTS(dcmfg)
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
- ../include/dcmtk/dcmfg/fgdefine.h ../include/dcmtk/dcmfg/fgtypes.h \
+ ../include/dcmtk/dcmfg/fgdefine.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../include/dcmtk/dcmfg/fgtypes.h \
../../ofstd/include/dcmtk/ofstd/oftempf.h \
../../ofstd/include/dcmtk/ofstd/oftest.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/offile.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
t_deriv_image.o: t_deriv_image.cc \
../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmfg/fgderimg.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
- ../../ofstd/include/dcmtk/ofstd/oftypes.h \
- ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
- ../../ofstd/include/dcmtk/ofstd/ofcast.h \
- ../../ofstd/include/dcmtk/ofstd/ofexport.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../../ofstd/include/dcmtk/ofstd/ofstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstream.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
- ../../ofstd/include/dcmtk/ofstd/oftraits.h \
- ../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
- ../../ofstd/include/dcmtk/ofstd/diag/push.def \
- ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
- ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../../ofstd/include/dcmtk/ofstd/oflimits.h \
- ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../oflog/include/dcmtk/oflog/config.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../../oflog/include/dcmtk/oflog/config/defines.h \
../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
../../oflog/include/dcmtk/oflog/loglevel.h \
../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
../../oflog/include/dcmtk/oflog/tchar.h \
../../oflog/include/dcmtk/oflog/spi/apndatch.h \
../../oflog/include/dcmtk/oflog/appender.h \
../../ofstd/include/dcmtk/ofstd/ofmem.h \
../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
../../oflog/include/dcmtk/oflog/layout.h \
../../oflog/include/dcmtk/oflog/streams.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../include/dcmtk/dcmfg/fgbase.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
- ../include/dcmtk/dcmfg/fgbase.h ../include/dcmtk/dcmfg/fgtypes.h \
- ../include/dcmtk/dcmfg/fgdefine.h \
+ ../include/dcmtk/dcmfg/fgtypes.h ../include/dcmtk/dcmfg/fgdefine.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
/*
*
- * Copyright (C) 2019-2024, OFFIS e.V.
+ * Copyright (C) 2019-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// Scanning done, now load
DcmFileFormat dcmff;
- OFVector<DcmIODTypes::Frame*> frames;
+ OFVector<DcmIODTypes::FrameBase*> frames;
result = cl.load("1.3.6.1.4.1.5962.1.7.70.2.1.1166562673.14401", dcmff.getDataset(), frames);
OFCHECK(result.good());
if (result.good())
DSET_DUMP += " (0018,1210) SH [STANDARD] # 8, 1 ConvolutionKernel\n";
DSET_DUMP += " (0018,9315) CS [ITERATIVE] # 10, 1 ReconstructionAlgorithm\n";
DSET_DUMP += " (0018,9316) CS [SOFT_TISSUE] # 12, 1 ConvolutionKernelGroup\n";
- DSET_DUMP += " (0018,9319) FD 360 # 8, 1 ReconstructionAngle\n";
+ DSET_DUMP += " (0018,9319) FD 360.00024414062494 # 8, 1 ReconstructionAngle\n";
DSET_DUMP += " (0018,9320) SH [None] # 4, 1 ImageFilter\n";
DSET_DUMP += " (0018,9322) FD 0.6347661018371581\\0.6347661018371581 # 16, 2 ReconstructionPixelSpacing\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (0018,9321) SQ (Sequence with undefined length #=1) # u/l, 1 CTExposureSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=5) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9323) CS [NONE] # 4, 1 ExposureModulationType\n";
- DSET_DUMP += " (0018,9328) FD 1000 # 8, 1 ExposureTimeInms\n";
- DSET_DUMP += " (0018,9330) FD 230 # 8, 1 XRayTubeCurrentInmA\n";
- DSET_DUMP += " (0018,9332) FD 230 # 8, 1 ExposureInmAs\n";
+ DSET_DUMP += " (0018,9328) FD 1000.0004882812499 # 8, 1 ExposureTimeInms\n";
+ DSET_DUMP += " (0018,9330) FD 230.00012207031247 # 8, 1 XRayTubeCurrentInmA\n";
+ DSET_DUMP += " (0018,9332) FD 230.00012207031247 # 8, 1 ExposureInmAs\n";
DSET_DUMP += " (0018,9345) FD (no value available) # 0, 0 CTDIvol\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-10.00000762939453 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-10.00000762939453 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-10.00000762939453 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-10.00000762939453 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -10.00000762939453 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-17.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-17.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-17.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-17.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -17.00143432617187 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-24.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-24.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -24.0029 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-24.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-24.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -24.002853393554684 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-31.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-31.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -31.0043 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-31.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-31.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -31.004272460937496 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-38.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-38.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-38.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-38.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -37.99575805664062 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-45.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-45.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-45.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-45.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -44.99716186523437 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-52.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-52.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-52.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-52.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -51.99859619140624 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-59.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-59.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-59.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-59.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -59.00003051757812 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-66.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-66.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-66.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-66.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -66.00146484374999 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-73.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-73.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-73.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-73.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -73.00286865234374 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-80.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-80.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-80.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-80.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -80.00433349609374 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-87.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-87.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-87.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-87.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -86.99578857421874 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-94.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-94.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-94.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-94.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -93.99719238281249 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-101 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-101 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -100.999 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-101.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-101.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -100.99859619140624 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-108 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-108 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -108 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-108.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-108.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -108.00006103515624 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-115 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-115 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -115.001 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-115.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-115.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -115.00146484374999 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-122 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-122 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -122.003 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-122.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-122.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -122.00286865234374 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-129 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-129 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -129.004 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-129.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-129.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -129.00439453124997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-136 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-136 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -135.996 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-136.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-136.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -135.99584960937497 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-143 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-143 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -142.997 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-143.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-143.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -142.99719238281247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-150 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-150 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -149.999 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-150.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-150.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -149.99865722656247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-157 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-157 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -157 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-157.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-157.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -157.00012207031247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-164 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-164 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -164.001 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-164.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-164.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -164.00146484374997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-171 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-171 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -171.003 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-171.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-171.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -171.00292968749997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-178 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-178 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -178.004 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-178.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-178.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -178.00439453124997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-185 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-185 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -184.996 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-185.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-185.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -184.99584960937497 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-192 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-192 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -191.997 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-192.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-192.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -191.99719238281247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-199 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-199 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -198.999 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-199.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-199.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -198.99865722656247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-206 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-206 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -206 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-206.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-206.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -206.00012207031247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-213 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-213 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -213.001 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-213.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-213.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -213.00146484374997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-10.00000762939453 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-10.00000762939453 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-10.00000762939453 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-10.00000762939453 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -10.00000762939453 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-17.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-17.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-17.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-17.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -17.00143432617187 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-24.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-24.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -24.0029 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-24.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-24.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -24.002853393554684 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-31.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-31.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -31.0043 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-31.00001525878906 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-31.00001525878906 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -31.004272460937496 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-38.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-38.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-38.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-38.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -37.99575805664062 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-45.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-45.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-45.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-45.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -44.99716186523437 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-52.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-52.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-52.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-52.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -51.99859619140624 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-59.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-59.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-59.00003051757812 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-59.00003051757812 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -59.00003051757812 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-66.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-66.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-66.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-66.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -66.00146484374999 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-73.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-73.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-73.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-73.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -73.00286865234374 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-80.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-80.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-80.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-80.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -80.00433349609374 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-87.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-87.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-87.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-87.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -86.99578857421874 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-94.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-94.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-94.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-94.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
DSET_DUMP += " (0018,9327) FD -93.99719238281249 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-101 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-101 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -100.999 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-101.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-101.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -100.99859619140624 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-108 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-108 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -108 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-108.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-108.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -108.00006103515624 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-115 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-115 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -115.001 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-115.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-115.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -115.00146484374999 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-122 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-122 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -122.003 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-122.00006103515624 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-122.00006103515624 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -122.00286865234374 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-129 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-129 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -129.004 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-129.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-129.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -129.00439453124997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-136 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-136 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -135.996 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-136.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-136.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -135.99584960937497 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-143 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-143 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -142.997 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-143.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-143.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -142.99719238281247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-150 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-150 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -149.999 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-150.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-150.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -149.99865722656247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-157 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-157 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -157 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-157.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-157.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -157.00012207031247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-164 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-164 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -164.001 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-164.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-164.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -164.00146484374997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-171 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-171 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -171.003 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-171.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-171.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -171.00292968749997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-178 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-178 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -178.004 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-178.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-178.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -178.00439453124997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-185 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-185 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -184.996 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-185.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-185.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -184.99584960937497 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-192 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-192 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -191.997 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-192.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-192.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -191.99719238281247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-199 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-199 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -198.999 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-199.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-199.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -198.99865722656247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-206 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-206 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -206 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-206.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-206.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -206.00012207031247 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=4) # u/l, 1 Item\n";
DSET_DUMP += " (0018,9326) SQ (Sequence with undefined length #=1) # u/l, 1 CTPositionSequence\n";
DSET_DUMP += " (fffe,e000) na (Item with undefined length #=3) # u/l, 1 Item\n";
- DSET_DUMP += " (0018,9313) FD 3.08271\\-0.3172872066497802\\-213 # 24, 3 DataCollectionCenterPatient\n";
- DSET_DUMP += " (0018,9318) FD 3.08271\\-0.3172872066497802\\-213 # 24, 3 ReconstructionTargetCenterPatient\n";
- DSET_DUMP += " (0018,9327) FD -213.001 # 8, 1 TablePosition\n";
+ DSET_DUMP += " (0018,9313) FD 3.0827140808105464\\-0.3172872066497802\\-213.00012207031247 # 24, 3 DataCollectionCenterPatient\n";
+ DSET_DUMP += " (0018,9318) FD 3.0827140808105464\\-0.3172872066497802\\-213.00012207031247 # 24, 3 ReconstructionTargetCenterPatient\n";
+ DSET_DUMP += " (0018,9327) FD -213.00146484374997 # 8, 1 TablePosition\n";
DSET_DUMP += " (fffe,e00d) na (ItemDelimitationItem) # 0, 0 ItemDelimitationItem\n";
DSET_DUMP += " (fffe,e0dd) na (SequenceDelimitationItem) # 0, 0 SequenceDelimitationItem\n";
DSET_DUMP += " (0018,9341) SQ (Sequence with undefined length #=2) # u/l, 1 ContrastBolusUsageSequence\n";
/*
*
- * Copyright (C) 2022-2024, OFFIS e.V.
+ * Copyright (C) 2022-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
FGUnknown* fg_copy = OFstatic_cast(FGUnknown*, fg.clone());
OFCHECK(fg_copy != NULL);
OFCHECK(fg.compare(*fg_copy) == 0);
+ delete fg_copy;
}
\section dcm2pnm_copyright COPYRIGHT
-Copyright (C) 1998-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1998-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmicmp_copyright COPYRIGHT
-Copyright (C) 2018-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2018-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmquant_copyright COPYRIGHT
-Copyright (C) 2001-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2001-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmscale_copyright COPYRIGHT
-Copyright (C) 2002-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2002-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 1996-2016, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
if (pixel != NULL)
{
- this->Data = new T[this->Count];
+ this->Data = new (std::nothrow) T[this->Count];
if (this->Data != NULL)
{
const T *r = pixel[0];
/*
*
- * Copyright (C) 1996-2016, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual ~DiColorPixelTemplate()
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
- /* use a non-throwing delete (if available) */
operator delete[] (Data[0], std::nothrow);
operator delete[] (Data[1], std::nothrow);
operator delete[] (Data[2], std::nothrow);
-#else
- delete[] Data[0];
- delete[] Data[1];
- delete[] Data[2];
-#endif
}
/** get integer representation
data = new Uint32[count];
if (data != NULL)
{
- Uint32 *q = OFstatic_cast(Uint32 *, data);
+ Uint8 *q = OFstatic_cast(Uint8 *, data);
if (fromBits == toBits)
{
/* copy pixel data as is */
{
for (x = width; x != 0; x--)
{
- /* normal sample order: 0-R-G-B */
- *(q++) = (OFstatic_cast(Uint32, *(r++)) << 16) |
- (OFstatic_cast(Uint32, *(g++)) << 8) |
- OFstatic_cast(Uint32, *(b++));
+ /* sample order: B-G-R-0 */
+ *(q++) = OFstatic_cast(Uint8, *(b++));
+ *(q++) = OFstatic_cast(Uint8, *(g++));
+ *(q++) = OFstatic_cast(Uint8, *(r++));
+ *(q++) = 0;
}
r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
}
{
for (x = width; x != 0; x--)
{
- /* normal sample order: 0-R-G-B */
- *(q++) = (OFstatic_cast(Uint32, *(r++) * gradient2) << 16) |
- (OFstatic_cast(Uint32, *(g++) * gradient2) << 8) |
- OFstatic_cast(Uint32, *(b++) * gradient2);
+ /* sample order: B-G-R-0 */
+ *(q++) = OFstatic_cast(Uint8, *(b++) * gradient2);
+ *(q++) = OFstatic_cast(Uint8, *(g++) * gradient2);
+ *(q++) = OFstatic_cast(Uint8, *(r++) * gradient2);
+ *(q++) = 0;
}
r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
}
{
for (x = width; x != 0; x--)
{
- /* normal sample order: 0-R-G-B */
- *(q++) = (OFstatic_cast(Uint32, OFstatic_cast(double, *(r++)) * gradient1) << 16) |
- (OFstatic_cast(Uint32, OFstatic_cast(double, *(g++)) * gradient1) << 8) |
- OFstatic_cast(Uint32, OFstatic_cast(double, *(b++)) * gradient1);
+ /* sample order: B-G-R-0 */
+ *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(b++)) * gradient1);
+ *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(g++)) * gradient1);
+ *(q++) = OFstatic_cast(Uint8, OFstatic_cast(double, *(r++)) * gradient1);
+ *(q++) = 0;
}
r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
}
{
for (x = width; x != 0; x--)
{
- /* normal sample order: 0-R-G-B */
- *(q++) = (OFstatic_cast(Uint32, *(r++) >> shift) << 16) |
- (OFstatic_cast(Uint32, *(g++) >> shift) << 8) |
- OFstatic_cast(Uint32, *(b++) >> shift);
+ /* sample order: B-G-R-0 */
+ *(q++) = OFstatic_cast(Uint8, *(b++) >> shift);
+ *(q++) = OFstatic_cast(Uint8, *(g++) >> shift);
+ *(q++) = OFstatic_cast(Uint8, *(r++) >> shift);
+ *(q++) = 0;
}
r += nextRow; g += nextRow; b += nextRow; // go backwards if 'upsideDown'
}
/* allocate data buffer for the 3 planes */
for (int j = 0; j < 3; j++)
{
-#ifdef HAVE_STD__NOTHROW
/* use a non-throwing new here (if available) because the allocated buffer can be huge */
Data[j] = new (std::nothrow) T[Count];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- Data[j] = new T[Count];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- Data[j] = NULL;
- }
-#endif
if (Data[j] != NULL)
{
/* erase empty part of the buffer (=blacken the background) */
if (InputCount < Count)
- OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, Count - InputCount);
+ {
+ const size_t count = (Count - InputCount);
+ DCMIMAGE_TRACE("filing empty part of the intermediate pixel data (" << count << " pixels) of plane " << j << " with value = 0");
+ OFBitmanipTemplate<T>::zeroMem(Data[j] + InputCount, count);
+ }
} else {
DCMIMAGE_DEBUG("cannot allocate memory buffer for 'Data[" << j << "]' in DiColorPixelTemplate::Init()");
result = 0; // at least one buffer could not be allocated!
/*
*
- * Copyright (C) 2002-2021, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmimage/dicdefin.h"
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
/* needed e.g. on Solaris for definition of size_t */
#include <sys/types.h>
-#endif
END_EXTERN_C
/** helper structure for class DcmQuantPixelBoxArray.
/*
*
- * Copyright (C) 1998-2016, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#define DIYBRPXT_H
#include "dcmtk/config/osconfig.h"
+#include "dcmtk/ofstd/ofbmanip.h"
#include "dcmtk/dcmimage/dicopxt.h"
#include "dcmtk/dcmimgle/diinpx.h" /* gcc 3.4 needs this */
// use the number of input pixels derived from the length of the 'PixelData'
// attribute), but not more than the size of the intermediate buffer
const unsigned long count = (this->InputCount < this->Count) ? this->InputCount : this->Count;
- if (rgb) /* convert to RGB model */
+ // make sure that there is sufficient input data (for planar pixel data)
+ if (!this->PlanarConfiguration || (count >= planeSize))
{
- T2 *r = this->Data[0];
- T2 *g = this->Data[1];
- T2 *b = this->Data[2];
- const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits));
- DiPixelRepresentationTemplate<T1> rep;
- if (bits == 8 && !rep.isSigned()) // only for unsigned 8 bit
+ if (rgb) /* convert to RGB model */
{
- Sint16 rcr_tab[256];
- Sint16 gcb_tab[256];
- Sint16 gcr_tab[256];
- Sint16 bcb_tab[256];
- const double r_const = 0.7010 * OFstatic_cast(double, maxvalue);
- const double g_const = 0.5291 * OFstatic_cast(double, maxvalue);
- const double b_const = 0.8859 * OFstatic_cast(double, maxvalue);
- unsigned long l;
- for (l = 0; l < 256; ++l)
+ T2 *r = this->Data[0];
+ T2 *g = this->Data[1];
+ T2 *b = this->Data[2];
+ const T2 maxvalue = OFstatic_cast(T2, DicomImageClass::maxval(bits));
+ DiPixelRepresentationTemplate<T1> rep;
+ if (bits == 8 && !rep.isSigned()) // only for unsigned 8 bit
{
- rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * OFstatic_cast(double, l) - r_const);
- gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * OFstatic_cast(double, l));
- gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * OFstatic_cast(double, l) - g_const);
- bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * OFstatic_cast(double, l) - b_const);
- }
- Sint32 sr;
- Sint32 sg;
- Sint32 sb;
- if (this->PlanarConfiguration)
- {
-/*
- const T1 *y = pixel;
- const T1 *cb = y + this->InputCount;
- const T1 *cr = cb + this->InputCount;
- for (i = count; i != 0; --i, ++y, ++cb, ++cr)
+ Sint16 rcr_tab[256];
+ Sint16 gcb_tab[256];
+ Sint16 gcr_tab[256];
+ Sint16 bcb_tab[256];
+ const double r_const = 0.7010 * OFstatic_cast(double, maxvalue);
+ const double g_const = 0.5291 * OFstatic_cast(double, maxvalue);
+ const double b_const = 0.8859 * OFstatic_cast(double, maxvalue);
+ unsigned long l;
+ for (l = 0; l < 256; ++l)
{
- sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[*cr]);
- sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
- sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[*cb]);
- *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
- *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
- *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ rcr_tab[l] = OFstatic_cast(Sint16, 1.4020 * OFstatic_cast(double, l) - r_const);
+ gcb_tab[l] = OFstatic_cast(Sint16, 0.3441 * OFstatic_cast(double, l));
+ gcr_tab[l] = OFstatic_cast(Sint16, 0.7141 * OFstatic_cast(double, l) - g_const);
+ bcb_tab[l] = OFstatic_cast(Sint16, 1.7720 * OFstatic_cast(double, l) - b_const);
}
+ Sint32 sr;
+ Sint32 sg;
+ Sint32 sb;
+ if (this->PlanarConfiguration)
+ {
+/*
+ const T1 *y = pixel;
+ const T1 *cb = y + this->InputCount;
+ const T1 *cr = cb + this->InputCount;
+ for (i = count; i != 0; --i, ++y, ++cb, ++cr)
+ {
+ sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[*cr]);
+ sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[*cb]) - OFstatic_cast(Sint32, gcr_tab[*cr]);
+ sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[*cb]);
+ *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
+ *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
+ *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ }
*/
- const T1 *y = pixel;
- const T1 *cb = y + planeSize;
- const T1 *cr = cb + planeSize;
- unsigned long i = count;
- while (i != 0)
+ const T1 *y = pixel;
+ const T1 *cb = y + planeSize;
+ const T1 *cr = cb + planeSize;
+ unsigned long i = count;
+ while (i != 0)
+ {
+ /* convert a single frame */
+ for (l = planeSize; (l != 0) && (i != 0); --l, --i, ++y, ++cb, ++cr)
+ {
+ const Sint32 yValue = *y;
+ /* conversion to unsigned integer needed for gcc 14 on Solaris */
+ const unsigned int cbValue = *cb;
+ const unsigned int crValue = *cr;
+ sr = yValue + rcr_tab[crValue];
+ sg = yValue - gcb_tab[cbValue] - gcr_tab[crValue];
+ sb = yValue + bcb_tab[cbValue];
+ *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
+ *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
+ *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ }
+ /* jump to next frame start (skip 2 planes) */
+ y += 2 * planeSize;
+ cb += 2 * planeSize;
+ cr += 2 * planeSize;
+ }
+ }
+ else
{
- /* convert a single frame */
- for (l = planeSize; (l != 0) && (i != 0); --l, --i, ++y, ++cb, ++cr)
+ const T1 *p = pixel;
+ unsigned long i;
+ for (i = count; i != 0; --i)
{
- sr = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, *cr)]);
- sg = OFstatic_cast(Sint32, *y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, *cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, *cr)]);
- sb = OFstatic_cast(Sint32, *y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, *cb)]);
+ const Sint32 yValue = *(p++);
+ /* conversion to unsigned integer needed for gcc 14 on Solaris */
+ const unsigned int cbValue = *(p++);
+ const unsigned int crValue = *(p++);
+ sr = yValue + rcr_tab[crValue];
+ sg = yValue - gcb_tab[cbValue] - gcr_tab[crValue];
+ sb = yValue + bcb_tab[cbValue];
*(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
*(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
*(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
}
- /* jump to next frame start (skip 2 planes) */
- y += 2 * planeSize;
- cb += 2 * planeSize;
- cr += 2 * planeSize;
}
}
else
{
- const T1 *p = pixel;
- T1 y;
- T1 cb;
- T1 cr;
- unsigned long i;
- for (i = count; i != 0; --i)
+ if (this->PlanarConfiguration)
+ {
+/*
+ const T1 *y = pixel;
+ const T1 *cb = y + this->InputCount;
+ const T1 *cr = cb + this->InputCount;
+ for (i = count; i != 0; --i)
+ convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset),
+ removeSign(*(cr++), offset), maxvalue);
+*/
+ unsigned long l;
+ unsigned long i = count;
+ const T1 *y = pixel;
+ const T1 *cb = y + planeSize;
+ const T1 *cr = cb + planeSize;
+ while (i != 0)
+ {
+ /* convert a single frame */
+ for (l = planeSize; (l != 0) && (i != 0); --l, --i)
+ {
+ const T2 yValue = removeSign(*(y++), offset);
+ const T2 cbValue = removeSign(*(cb++), offset);
+ const T2 crValue = removeSign(*(cr++), offset);
+ convertValue(*(r++), *(g++), *(b++), yValue, cbValue, crValue, maxvalue);
+ }
+ /* jump to next frame start (skip 2 planes) */
+ y += 2 * planeSize;
+ cb += 2 * planeSize;
+ cr += 2 * planeSize;
+ }
+ }
+ else
{
- y = *(p++);
- cb = *(p++);
- cr = *(p++);
- sr = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, rcr_tab[OFstatic_cast(Uint32, cr)]);
- sg = OFstatic_cast(Sint32, y) - OFstatic_cast(Sint32, gcb_tab[OFstatic_cast(Uint32, cb)]) - OFstatic_cast(Sint32, gcr_tab[OFstatic_cast(Uint32, cr)]);
- sb = OFstatic_cast(Sint32, y) + OFstatic_cast(Sint32, bcb_tab[OFstatic_cast(Uint32, cb)]);
- *(r++) = (sr < 0) ? 0 : (sr > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sr);
- *(g++) = (sg < 0) ? 0 : (sg > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sg);
- *(b++) = (sb < 0) ? 0 : (sb > OFstatic_cast(Sint32, maxvalue)) ? maxvalue : OFstatic_cast(T2, sb);
+ const T1 *p = pixel;
+ unsigned long i;
+ for (i = count; i != 0; --i)
+ {
+ const T2 yValue = removeSign(*(p++), offset);
+ const T2 cbValue = removeSign(*(p++), offset);
+ const T2 crValue = removeSign(*(p++), offset);
+ convertValue(*(r++), *(g++), *(b++), yValue, cbValue, crValue, maxvalue);
+ }
}
}
- }
- else
- {
+ } else { /* retain YCbCr model */
+ const T1 *p = pixel;
if (this->PlanarConfiguration)
{
/*
- const T1 *y = pixel;
- const T1 *cb = y + this->InputCount;
- const T1 *cr = cb + this->InputCount;
- for (i = count; i != 0; --i)
- convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset),
- removeSign(*(cr++), offset), maxvalue);
+ T2 *q;
+ // number of pixels to be skipped (only applicable if 'PixelData' contains more
+ // pixels than expected)
+ const unsigned long skip = (this->InputCount > this->Count) ? (this->InputCount - this->Count) : 0;
+ for (int j = 0; j < 3; ++j)
+ {
+ q = this->Data[j];
+ for (i = count; i != 0; --i)
+ *(q++) = removeSign(*(p++), offset);
+ // skip to beginning of next plane
+ p += skip;
+ }
*/
unsigned long l;
- unsigned long i = count;
- const T1 *y = pixel;
- const T1 *cb = y + planeSize;
- const T1 *cr = cb + planeSize;
- while (i != 0)
+ unsigned long i = 0;
+ while (i < count)
{
- /* convert a single frame */
- for (l = planeSize; (l != 0) && (i != 0); --l, --i)
+ /* store current pixel index */
+ const unsigned long iStart = i;
+ for (int j = 0; j < 3; ++j)
{
- convertValue(*(r++), *(g++), *(b++), removeSign(*(y++), offset), removeSign(*(cb++), offset),
- removeSign(*(cr++), offset), maxvalue);
+ /* convert a single plane */
+ for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i)
+ this->Data[j][i] = removeSign(*(p++), offset);
}
- /* jump to next frame start (skip 2 planes) */
- y += 2 * planeSize;
- cb += 2 * planeSize;
- cr += 2 * planeSize;
}
}
else
{
- const T1 *p = pixel;
- T2 y;
- T2 cb;
- T2 cr;
+ int j;
unsigned long i;
- for (i = count; i != 0; --i)
- {
- y = removeSign(*(p++), offset);
- cb = removeSign(*(p++), offset);
- cr = removeSign(*(p++), offset);
- convertValue(*(r++), *(g++), *(b++), y, cb, cr, maxvalue);
- }
- }
- }
- } else { /* retain YCbCr model */
- const T1 *p = pixel;
- if (this->PlanarConfiguration)
- {
-/*
- T2 *q;
- // number of pixels to be skipped (only applicable if 'PixelData' contains more
- // pixels than expected)
- const unsigned long skip = (this->InputCount > this->Count) ? (this->InputCount - this->Count) : 0;
- for (int j = 0; j < 3; ++j)
- {
- q = this->Data[j];
- for (i = count; i != 0; --i)
- *(q++) = removeSign(*(p++), offset);
- // skip to beginning of next plane
- p += skip;
- }
-*/
- unsigned long l;
- unsigned long i = 0;
- while (i < count)
- {
- /* store current pixel index */
- const unsigned long iStart = i;
- for (int j = 0; j < 3; ++j)
- {
- /* convert a single plane */
- for (l = planeSize, i = iStart; (l != 0) && (i < count); --l, ++i)
- this->Data[j][i] = removeSign(*(p++), offset);
- }
+ for (i = 0; i < count; ++i) /* for all pixel ... */
+ for (j = 0; j < 3; ++j)
+ this->Data[j][i] = removeSign(*(p++), offset); /* ... copy planes */
}
}
- else
- {
- int j;
- unsigned long i;
- for (i = 0; i < count; ++i) /* for all pixel ... */
- for (j = 0; j < 3; ++j)
- this->Data[j][i] = removeSign(*(p++), offset); /* ... copy planes */
- }
+ } else {
+ // do not process the input data, as it is too short
+ DCMIMAGE_WARN("input data is too short, filling the complete image with black pixels");
+ // erase empty part of the buffer (that has not been "blackened" yet)
+ for (int j = 0; j < 3; ++j)
+ OFBitmanipTemplate<T2>::zeroMem(this->Data[j], count);
}
}
}
../../ofstd/include/dcmtk/ofstd/diag/restrict.def \
../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \
../include/dcmtk/dcmimage/diqttype.h \
../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h
dicmyimg.o: dicmyimg.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../ofstd/include/dcmtk/ofstd/offile.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
- ../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../ofstd/include/dcmtk/ofstd/diag/restrict.def \
../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \
../include/dcmtk/dcmimage/diqttype.h
../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h
../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../../dcmdata/include/dcmtk/dcmdata/dcuid.h
diregist.o: diregist.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h
dirgbimg.o: dirgbimg.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../include/dcmtk/dcmimage/dicopx.h ../include/dcmtk/dcmimage/dilogger.h \
../include/dcmtk/dcmimage/dicdefin.h \
../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \
- ../include/dcmtk/dcmimage/diybrpxt.h ../include/dcmtk/dcmimage/dicopxt.h \
+ ../include/dcmtk/dcmimage/diybrpxt.h \
../../ofstd/include/dcmtk/ofstd/ofbmanip.h \
../../ofstd/include/dcmtk/ofstd/diag/stringop.def \
../../ofstd/include/dcmtk/ofstd/diag/restrict.def \
+ ../include/dcmtk/dcmimage/dicopxt.h \
../../dcmimgle/include/dcmtk/dcmimgle/dipxrept.h \
../../dcmimgle/include/dcmtk/dcmimgle/diinpx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didocu.h \
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#endif
END_EXTERN_C
+#if TIFFLIB_VERSION < 20050912
+#error TIFF library versions prior to 3.7.4 are not supported by DCMTK
+#endif
DiTIFFPlugin::DiTIFFPlugin()
: DiPluginFormat()
int stream_fd = fileno(stream);
-#ifdef HAVE_WINDOWS_H
-
-#if TIFFLIB_VERSION < 20050912
-#error TIFF library versions prior to 3.7.4 are not supported by DCMTK on Win32 - critical API change!
+#ifdef _WIN32
+
+ /* On Windows, TIFFFdOpen() expects a Windows HANDLE (which is a pointer
+ * type) instead of a file descriptor, but passes the file descriptor as an
+ * int. Despite HANDLE being a 64-bit type on Win64 and int being 32-bit,
+ * this is apparently safe, because Win64 guarantees to only use 32-bit
+ * handles, for interoperability reasons, as documented here:
+ *
+ * https://docs.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
+ *
+ * Therefore, we use _get_osfhandle() to access the HANDLE underlying the
+ * file descriptor.
+ */
+
+#ifdef __CYGWIN__
+ stream_fd = OFstatic_cast(int, get_osfhandle(stream_fd));
+#else
+ stream_fd = OFstatic_cast(int, _get_osfhandle(stream_fd));
#endif
-/* Older versions of libtiff expected a Win32 HANDLE when compiled on Windows
- * instead of a file descriptor. The code below was needed to make that work.
- * Libtiff version 3.7.4 and newer are known to use a file descriptor instead,
- * but it is not completely clear at which libtiff release the API change happened.
- *
- * #ifdef __CYGWIN__
- * stream_fd = OFstatic_cast(int, get_osfhandle(stream_fd));
- * #else
- * stream_fd =OFstatic_cast(int, _get_osfhandle(stream_fd));
- * #endif
- */
-
-#elif TIFFLIB_VERSION < 20041016
-#error TIFF library versions prior to 3.7.0 are not supported by DCMTK - TIFFCleanup is missing!
-#endif
+#endif /* _WIN32 */
/* create bitmap with 8 bits per sample */
void *data = OFconst_cast(void *, image->getOutputData(frame, 8 /*bits*/, 0 /*planar*/));
offset += bytesperrow;
}
TIFFFlushData(tif);
+
/* Clean up internal structures and free memory.
* However, the file will be closed by the caller, therefore
- * TIFFClose(tif) is not called.
+ * TIFFClose() is not called.
*/
TIFFCleanup(tif);
}
compressionType = ctype;
}
+
void DiTIFFPlugin::setLZWPredictor(DiTIFFLZWPredictor pred)
{
predictor = pred;
}
+
void DiTIFFPlugin::setRowsPerStrip(unsigned long rows)
{
rowsPerStrip = rows;
}
+
OFString DiTIFFPlugin::getLibraryVersionString()
{
/* use first line only, omit copyright information */
// compute initial maxval
maxval = OFstatic_cast(DcmQuantComponent, -1);
- DcmQuantColorHashTable *htable = NULL;
// attempt to make a histogram of the colors, unclustered.
// If at first we don't succeed, lower maxval to increase color
// coherence and try again. This will eventually terminate.
- OFBool done = OFFalse;
- while (! done)
+ do
{
- htable = new DcmQuantColorHashTable();
- numColors = htable->addToHashTable(image, maxval, maxcolors);
- if (numColors > 0) done = OFTrue;
- else
- {
- delete htable;
+ DcmQuantColorHashTable htable;
+ if (htable.addToHashTable(image, maxval, maxcolors) > 0)
+ {
+ numColors = htable.createHistogram(array);
+ return EC_Normal;
+ }
maxval = maxval/2;
- }
- }
-
- numColors = htable->createHistogram(array);
- delete htable;
- return EC_Normal;
+ } while (OFTrue);
}
\section dcmdspfn_copyright COPYRIGHT
-Copyright (C) 1999-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1999-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcod2lum_copyright COPYRIGHT
-Copyright (C) 2002-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2002-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dconvlum_copyright COPYRIGHT
-Copyright (C) 1999-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1999-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 1996-2021, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual ~DiInputPixelTemplate()
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
- /* use a non-throwing delete (if available) */
operator delete[] (Data, std::nothrow);
-#else
- delete[] Data;
-#endif
}
#include DCMTK_DIAGNOSTIC_PUSH
T2 *p = Data;
unsigned long i;
const double absrange = getAbsMaxRange();
+ const double absmin = getAbsMinimum();
const unsigned long ocnt = (absrange <= 10000000.0) ? OFstatic_cast(unsigned long, absrange) : 0 /* no LUT */;
Uint8 *lut = NULL;
if ((sizeof(T2) <= 2) && (ocnt > 0) && (Count > 3 * ocnt)) // optimization criteria
{
DCMIMGLE_DEBUG("using optimized routine with additional LUT");
OFBitmanipTemplate<Uint8>::zeroMem(lut, ocnt);
- Uint8 *q = lut - OFstatic_cast(T2, getAbsMinimum());
+ Uint8 *q = lut - OFstatic_cast(T2, absmin);
for (i = Count; i != 0; --i) // fill lookup table
*(q + *(p++)) = 1;
q = lut;
{
if (*(q++) != 0)
{
- MinValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i) + getAbsMinimum());
+ MinValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i) + absmin);
break;
}
}
{
if (*(--q) != 0)
{
- MaxValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + getAbsMinimum());
+ MaxValue[0] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + absmin);
break;
}
}
} else { // calculate min/max for selected range
OFBitmanipTemplate<Uint8>::zeroMem(lut, ocnt);
p = Data + PixelStart;
- q = lut - OFstatic_cast(T2, getAbsMinimum());
- for (i = PixelCount; i != 0; --i) // fill lookup table
+ q = lut - OFstatic_cast(T2, absmin);
+ for (i = PixelCount; i != 0; --i) // fill lookup table
*(q + *(p++)) = 1;
q = lut;
- for (i = 0; i < ocnt; ++i) // search for minimum
+ for (i = 0; i < ocnt; ++i) // search for minimum
{
if (*(q++) != 0)
{
- MinValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i) + getAbsMinimum());
+ MinValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i) + absmin);
break;
}
}
q = lut + ocnt;
- for (i = ocnt; i != 0; --i) // search for maximum
+ for (i = ocnt; i != 0; --i) // search for maximum
{
if (*(--q) != 0)
{
- MaxValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + getAbsMinimum());
+ MaxValue[1] = OFstatic_cast(T2, OFstatic_cast(double, i - 1) + absmin);
break;
}
}
/* Bits Allocated is always a multiple of 8 (see above), same for bits of T1 */
const Uint32 byteFactor = bitsAllocated / 8;
const Uint32 bytes_T1 = bitsof_T1 / 8;
- const Uint32 count_T1 = (byteFactor == bytes_T1) ? PixelCount : (PixelCount * byteFactor + bytes_T1 - 1) / bytes_T1;
+ const Uint32 count_T1 = OFstatic_cast(Uint32, (byteFactor == bytes_T1) ? PixelCount : (PixelCount * byteFactor + bytes_T1 - 1) / bytes_T1);
#ifdef DEBUG
DCMIMGLE_TRACE("PixelCount: " << PixelCount << ", byteFactor: " << byteFactor << ", bytes_T1: " << bytes_T1 << ", count_T1: " << count_T1);
#endif
/* allocate temporary buffer, even number of bytes required for getUncompressedFrame() */
const Uint32 extraByte = ((sizeof(T1) == 1) && (count_T1 & 1)) ? 1 : 0;
-#ifdef HAVE_STD__NOTHROW
+
/* use a non-throwing new here (if available) because the allocated buffer can be huge */
pixel = new (std::nothrow) T1[count_T1 + extraByte];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- pixel = new T1[count_T1 + extraByte];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- pixel = NULL;
- }
-#endif
if (pixel != NULL)
{
if (uncompressed)
{
DCMIMGLE_DEBUG("using partial read access to uncompressed pixel data");
- const Uint32 offset = PixelStart * byteFactor;
- const Uint32 bufSize = PixelCount * byteFactor;
+ const Uint32 offset = OFstatic_cast(Uint32, PixelStart * byteFactor);
+ const Uint32 bufSize = OFstatic_cast(Uint32, PixelCount * byteFactor);
const OFCondition status = pixelData->getPartialValue(pixel, offset, bufSize, fileCache);
if (status.good())
{
DCMIMGLE_DEBUG("using partial read access to compressed pixel data");
OFCondition status = EC_IllegalCall;
OFString decompressedColorModel;
- const Uint32 fsize = FrameSize * byteFactor;
+ const Uint32 fsize = OFstatic_cast(Uint32, FrameSize * byteFactor);
for (Uint32 frame = 0; frame < NumberOfFrames; ++frame)
{
/* make sure that the buffer always has an even number of bytes as required for getUncompressedFrame() */
const Uint32 bufSize = (fsize & 1) ? fsize + 1 : fsize;
- status = pixelData->getUncompressedFrame(document->getDataset(), FirstFrame + frame, fragment,
- OFreinterpret_cast(Uint8 *, pixel) + lengthBytes, bufSize, decompressedColorModel, fileCache);
+ status = pixelData->getUncompressedFrame(document->getDataset(), OFstatic_cast(Uint32, FirstFrame + frame),
+ fragment, OFreinterpret_cast(Uint8 *, pixel) + lengthBytes, bufSize, decompressedColorModel, fileCache);
if (status.good())
{
DCMIMGLE_TRACE("successfully decompressed frame " << FirstFrame + frame);
}
if ((pixel != NULL) && (lengthBytes > 0))
{
- const Uint32 length_T1 = lengthBytes / sizeof(T1);
+ const Uint32 length_T1 = OFstatic_cast(Uint32, lengthBytes / sizeof(T1));
/* need to split 'length' in order to avoid integer overflow for large pixel data */
const Uint32 length_B1 = lengthBytes / bitsAllocated;
const Uint32 length_B2 = lengthBytes % bitsAllocated;
// # old code: Count = ((lengthBytes * 8) + bitsAllocated - 1) / bitsAllocated;
Count = 8 * length_B1 + (8 * length_B2 + bitsAllocated - 1) / bitsAllocated;
unsigned long i;
-#ifdef HAVE_STD__NOTHROW
+
/* use a non-throwing new here (if available) because the allocated buffer can be huge */
Data = new (std::nothrow) T2[Count];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- Data = new T2[Count];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- Data = NULL;
- }
-#endif
if (Data != NULL)
{
DCMIMGLE_TRACE("Input length: " << lengthBytes << " bytes, Pixel count: " << Count
T2 smask = 0;
for (i = bitsStored; i < bitsof_T2; ++i)
smask |= OFstatic_cast(T2, 1 << i);
- const Uint16 shift = highBit + 1 - bitsStored;
+ const Uint16 shift = OFstatic_cast(Uint16, highBit + 1 - bitsStored);
if (shift == 0)
{
DCMIMGLE_DEBUG("convert input pixel data: case 1b (mask & sign)");
T2 smask = 0;
for (i = bitsStored; i < bitsof_T2; ++i)
smask |= OFstatic_cast(T2, 1 << i);
- const Uint16 shift = highBit + 1 - bitsStored;
+ const Uint16 shift = OFstatic_cast(Uint16, highBit + 1 - bitsStored);
for (i = length_T1; i != 0; --i)
{
value = *(p++) >> shift;
value >>= bitsAllocated;
}
}
+ /* check whether there are any remaining pixel values to be processed */
+ const signed int rest = OFstatic_cast(int, Count - length_T1 * times);
+ if (rest > 0)
+ {
+ /* usually, there is only a single final pixel value */
+ if (rest == 1)
+ DCMIMGLE_TRACE(" there is still " << rest << " pixel value to be processed, so let's do it");
+ else
+ DCMIMGLE_TRACE(" there are still " << rest << " pixel values to be processed, so let's do it");
+ value = *(p++) >> shift;
+ for (j = OFstatic_cast(Uint16, rest); j != 0; --j)
+ {
+ *(q++) = expandSign(OFstatic_cast(T2, value & mask), sign, smask);
+ value >>= bitsAllocated;
+ }
+ }
}
}
else if ((bitsof_T1 < bitsAllocated) && (bitsAllocated % bitsof_T1 == 0) // case 3: multiplicand of 8/16
T1 mask[bitsof_T1];
mask[0] = 1;
for (i = 1; i < bitsof_T1; ++i)
- mask[i] = (mask[i - 1] << 1) | 1;
+ mask[i] = OFstatic_cast(T1, (mask[i - 1] << 1) | 1);
T2 smask = 0;
for (i = bitsStored; i < bitsof_T2; ++i)
smask |= OFstatic_cast(T2, 1 << i);
skip -= times * bitsof_T1;
}
}
+ /* fill the remaining entry (if any) with the smallest value that is possible */
+ if (q < Data + Count)
+ {
+ DCMIMGLE_TRACE("not enough data, filling last entry of input buffer with value = " << getAbsMinimum());
+ *q = OFstatic_cast(T2, getAbsMinimum());
+ }
+
}
} else
DCMIMGLE_DEBUG("cannot allocate memory buffer for 'Data' in DiInputPixelTemplate::convert()");
if (deletePixel)
{
/* delete temporary buffer */
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
- /* use a non-throwing delete (if available) */
operator delete[] (pixel, std::nothrow);
-#else
- delete[] pixel;
-#endif
}
}
/*
*
- * Copyright (C) 1996-2011, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dctagkey.h"
+#include "dcmtk/dcmdata/dcvrobow.h"
#include "dcmtk/dcmimgle/dibaslut.h"
#include "dcmtk/dcmimgle/diobjcou.h"
const signed long first = -1,
EI_Status *status = NULL);
+
+ /** constructor
+ *
+ ** @param data element containing the LUT data (must be of VR=OW)
+ * @param descriptor element containing the LUT descriptor
+ * @param explanation element containing the LUT explanation (optional)
+ * @param descripMode mode specifying the use of the bits per table entry value
+ * @param first expected value for "first input value mapped" (optional)
+ * @param status pointer to image status variable (optional)
+ */
+ DiLookupTable(const DcmOtherByteOtherWord &data,
+ const DcmUnsignedShort &descriptor,
+ const DcmLongString *explanation = NULL,
+ const EL_BitsPerTableEntry descripMode = ELM_UseValue,
+ const signed long first = -1,
+ EI_Status *status = NULL);
+
/** constructor
*
** @param buffer pointer to array with LUT entries
int compareLUT(const DcmUnsignedShort &data,
const DcmUnsignedShort &descriptor);
+ /** compares current LUT with specified LUT
+ *
+ ** @param data element containing the LUT data (must be of VR=OW)
+ * @param descriptor element containing the LUT descriptor
+ *
+ ** @return true if LUTs are not equal (1 = invalid LUT / memory error,
+ * 2 = descriptor differs,
+ * 3 = data differs)
+ * false (0) otherwise
+ */
+ int compareLUT(const DcmOtherByteOtherWord &data,
+ const DcmUnsignedShort &descriptor);
+
/** compares current LUT with specified LUT
*
const EL_BitsPerTableEntry descripMode = ELM_UseValue,
EI_Status *status = NULL);
+ /** initialize lookup table
+ *
+ ** @param data array containing the LUT data
+ * @param count number of entries in LUT data array
+ * @param descriptor element containing the LUT descriptor
+ * @param explanation element containing the LUT explanation (optional)
+ * @param descripMode mode specifying the use of the bits per table entry value
+ * @param first expected value for "first input value mapped" (optional)
+ * @param status pointer to image status variable (optional)
+ */
+ void Init(const Uint16 *data,
+ const unsigned long count,
+ const DcmUnsignedShort &descriptor,
+ const DcmLongString *explanation = NULL,
+ const EL_BitsPerTableEntry descripMode = ELM_UseValue,
+ const signed long first = -1,
+ EI_Status *status = NULL);
+
/** check (and possibly correct) lookup table for consistency
*
** @param count number of LUT entries
/*
*
- * Copyright (C) 1996-2010, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
if (pixel != NULL)
{
- this->Data = new T[this->getCount()];
+ this->Data = new (std::nothrow) T[this->getCount()];
if (this->Data != NULL)
OFBitmanipTemplate<T>::copyMem(pixel, this->Data, this->getCount());
}
/*
*
- * Copyright (C) 1996-2011, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
if (pixel != NULL)
{
- this->Data = new T[this->getCount()];
+ this->Data = new (std::nothrow) T[this->getCount()];
if (this->Data != NULL)
{
if (horz && vert)
/*
*
- * Copyright (C) 1996-2021, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofbmanip.h"
#include "dcmtk/ofstd/ofcast.h"
#include "dcmtk/ofstd/ofdiag.h" /* for DCMTK_DIAGNOSTIC macros */
+#include "dcmtk/ofstd/oflimits.h" /* for OFnumeric_limits<> */
#include "dcmtk/dcmimgle/dimopxt.h"
#include "dcmtk/dcmimgle/diinpx.h"
DiMonoModality *modality)
: DiMonoPixelTemplate<T3>(pixel, modality)
{
- if ((pixel != NULL) && (this->Count > 0))
+ if ((pixel != NULL) && (this->Modality != NULL) && (this->Count > 0))
{
// check whether to apply any modality transform
- if ((this->Modality != NULL) && this->Modality->hasLookupTable() && (bitsof(T1) <= MAX_TABLE_ENTRY_SIZE))
+ if (this->Modality->hasLookupTable() && (bitsof(T1) <= MAX_TABLE_ENTRY_SIZE))
{
modlut(pixel);
// ignore modality LUT min/max values since the image does not necessarily have to use all LUT entries
this->determineMinMax();
}
- else if ((this->Modality != NULL) && this->Modality->hasRescaling())
+ else if (this->Modality->hasRescaling())
{
rescale(pixel, this->Modality->getRescaleSlope(), this->Modality->getRescaleIntercept());
this->determineMinMax(OFstatic_cast(T3, this->Modality->getMinValue()), OFstatic_cast(T3, this->Modality->getMaxValue()));
rescale(pixel); // "copy" or reference pixel data
this->determineMinMax(OFstatic_cast(T3, this->Modality->getMinValue()), OFstatic_cast(T3, this->Modality->getMaxValue()));
}
- /* erase empty part of the buffer (= blacken the background) */
+ /* erase empty part of the buffer */
if ((this->Data != NULL) && (this->InputCount < this->Count))
- OFBitmanipTemplate<T3>::zeroMem(this->Data + this->InputCount, this->Count - this->InputCount);
+ {
+ /* that means, fill the background with the smallest value that is possible */
+ const T3 minOut = OFnumeric_limits<T3>::min();
+ const T3 background = (this->Modality->getAbsMinimum() < OFstatic_cast(double, minOut)) ? minOut : OFstatic_cast(T3, this->Modality->getAbsMinimum());
+ const size_t count = (this->Count - this->InputCount);
+ DCMIMGLE_DEBUG("filing empty part of the intermediate pixel data (" << count << " pixels) with value = " << OFstatic_cast(double, background));
+ OFBitmanipTemplate<T3>::setMem(this->Data + this->InputCount, background, count);
+ }
}
}
this->Data = OFstatic_cast(T3 *, input->getDataPtr());
input->removeDataReference(); // avoid double deletion
} else
- this->Data = new T3[this->Count];
+ this->Data = new (std::nothrow) T3[this->Count];
if (this->Data != NULL)
{
DCMIMGLE_DEBUG("applying modality transformation with LUT (" << mlut->getCount() << " entries)");
this->Data = OFstatic_cast(T3 *, input->getDataPtr());
input->removeDataReference(); // avoid double deletion
} else
- this->Data = new T3[this->Count];
+ this->Data = new (std::nothrow) T3[this->Count];
if (this->Data != NULL)
{
T3 *q = this->Data;
/*
*
- * Copyright (C) 1996-2016, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
MaxValue[0] = 0;
MaxValue[1] = 0;
// allocate buffer of given size
-#ifdef HAVE_STD__NOTHROW
+
/* use a non-throwing new here (if available) because the allocated buffer can be huge */
Data = new (std::nothrow) T[Count];
-#else
- /* make sure that the pointer is set to NULL in case of error */
- try
- {
- Data = new T[Count];
- }
- catch (STD_NAMESPACE bad_alloc const &)
- {
- Data = NULL;
- }
-#endif
if (Data == NULL)
DCMIMGLE_DEBUG("cannot allocate memory buffer for 'Data' in DiMonoPixelTemplate constructor");
}
*/
virtual ~DiMonoPixelTemplate()
{
-#if defined(HAVE_STD__NOTHROW) && defined(HAVE_NOTHROW_DELETE)
- /* use a non-throwing delete (if available) */
operator delete[] (Data, std::nothrow);
-#else
- delete[] Data;
-#endif
}
/** get integer representation
/*
*
- * Copyright (C) 1996-2011, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
if (pixel != NULL)
{
- this->Data = new T[DiMonoPixelTemplate<T>::getCount()];
+ this->Data = new (std::nothrow) T[DiMonoPixelTemplate<T>::getCount()];
if (this->Data != NULL)
{
if (degree == 90)
/*
*
- * Copyright (C) 1996-2011, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
if (pixel != NULL)
{
- this->Data = new T[this->getCount()];
+ this->Data = new (std::nothrow) T[this->getCount()];
if (this->Data != NULL)
{
const T value = OFstatic_cast(T, OFstatic_cast(double, DicomImageClass::maxval(bits)) *
/*
*
- * Copyright (C) 1996-2018, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/** @name configuration flags
*/
-
-//@{
+///@{
/// compatibility with old ACR-NEMA images
const unsigned long CIF_AcrNemaCompatibility = 0x0000001;
/// never access embedded overlays since this requires to load and uncompress the complete pixel data
const unsigned long CIF_NeverAccessEmbeddedOverlays = 0x0001000;
-//@}
+
+///@}
// / true color color mode (for monochrome images only)
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../include/dcmtk/dcmimgle/dimo1img.h ../include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../include/dcmtk/dcmimgle/diregbas.h \
../include/dcmtk/dcmimgle/diplugin.h
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
+ ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/diutils.h \
+ ../include/dcmtk/dcmimgle/didefine.h \
../../ofstd/include/dcmtk/ofstd/ofbmanip.h \
../../ofstd/include/dcmtk/ofstd/diag/stringop.def \
../../ofstd/include/dcmtk/ofstd/diag/restrict.def \
../include/dcmtk/dcmimgle/diluptab.h \
- ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/diutils.h \
- ../include/dcmtk/dcmimgle/didefine.h \
../include/dcmtk/dcmimgle/diobjcou.h ../include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h
dimo2img.o: dimo2img.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h
dimoimg.o: dimoimg.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../include/dcmtk/dcmimgle/diregbas.h
dimoimg3.o: dimoimg3.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h \
../include/dcmtk/dcmimgle/dimoipxt.h \
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h \
../include/dcmtk/dcmimgle/dimoipxt.h \
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h \
../include/dcmtk/dcmimgle/dimoipxt.h \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
- ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/diutils.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../oflog/include/dcmtk/oflog/config.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/didefine.h \
- ../include/dcmtk/dcmimgle/diobjcou.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../include/dcmtk/dcmimgle/didocu.h \
- ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../include/dcmtk/dcmimgle/diobjcou.h ../include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../../ofstd/include/dcmtk/ofstd/offile.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
- ../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
- ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
- ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
- ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../include/dcmtk/dcmimgle/dibaslut.h \
- ../include/dcmtk/dcmimgle/diobjcou.h \
- ../../ofstd/include/dcmtk/ofstd/ofthread.h
+ ../include/dcmtk/dcmimgle/diobjcou.h
dimopx.o: dimopx.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmimgle/dimopx.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
- ../include/dcmtk/dcmimgle/dibaslut.h \
- ../include/dcmtk/dcmimgle/diobjcou.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../include/dcmtk/dcmimgle/diinpx.h ../include/dcmtk/dcmimgle/dimoopx.h
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../include/dcmtk/dcmimgle/dibaslut.h \
+ ../include/dcmtk/dcmimgle/diobjcou.h ../include/dcmtk/dcmimgle/diinpx.h \
+ ../include/dcmtk/dcmimgle/dimoopx.h
diovdat.o: diovdat.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../include/dcmtk/dcmimgle/diovpln.h ../include/dcmtk/dcmimgle/diutils.h \
../include/dcmtk/dcmimgle/dimopx.h ../include/dcmtk/dcmimgle/dipixel.h \
../include/dcmtk/dcmimgle/dimomod.h ../include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../include/dcmtk/dcmimgle/dibaslut.h ../include/dcmtk/dcmimgle/dimoopx.h \
../include/dcmtk/dcmimgle/didispfn.h ../include/dcmtk/dcmimgle/dimopxt.h \
../../ofstd/include/dcmtk/ofstd/ofbmanip.h \
../include/dcmtk/dcmimgle/dipxrept.h ../include/dcmtk/dcmimgle/didocu.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h
diovpln.o: diovpln.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
/*
*
- * Copyright (C) 1996-2024, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*(q++) = c;
}
*q = '\0'; // end of C string
+ DCMIMGLE_DEBUG("filtered version of 'PhotometricInterpretation' = " << OFSTRING_GUARD(cstr));
while ((pin->Name != NULL) && (strcmp(pin->Name, cstr) != 0))
++pin;
delete[] cstr;
/*
*
- * Copyright (C) 1999-2021, OFFIS e.V.
+ * Copyright (C) 1999-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
if (Count == ddl_cnt) // check whether CIELAB LUT fits exactly to DISPLAY file
{
+ /* use the standard "C" locale for proper decimal point */
+ const STD_NAMESPACE locale oldLocale = stream->imbue(STD_NAMESPACE locale("C"));
for (i = 0; i < ddl_cnt; ++i)
{
(*stream) << ddl_tab[i]; // DDL
}
(*stream) << OFendl;
}
+ /* reset locale */
+ stream->imbue(oldLocale);
} else {
DCMIMGLE_WARN("can't write curve data, wrong DISPLAY file or CIELAB LUT");
}
/*
*
- * Copyright (C) 1996-2024, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
status = PixelData->getDecompressedColorModel(OFstatic_cast(DcmItem *, Object), PhotometricInterpretation);
if (status.bad())
{
- DCMIMGLE_ERROR("can't determine 'PhotometricInterpretation' of decompressed image");
+ if (Flags & CIF_AcrNemaCompatibility)
+ {
+ DCMIMGLE_WARN("can't determine 'PhotometricInterpretation' of decompressed image "
+ << "... assuming MONOCHROME2 (ACR-NEMA compatibility)");
+ } else
+ DCMIMGLE_ERROR("can't determine 'PhotometricInterpretation' of decompressed image");
DCMIMGLE_DEBUG("DcmPixelData::getDecompressedColorModel() returned: " << status.text());
}
} else {
/*
*
- * Copyright (C) 1999-2021, OFFIS e.V.
+ * Copyright (C) 1999-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
if (Count == ddl_cnt) // check whether GSDF LUT fits exactly to DISPLAY file
{
+ /* use the standard "C" locale for proper decimal point */
+ const STD_NAMESPACE locale oldLocale = stream->imbue(STD_NAMESPACE locale("C"));
for (i = 0; i < ddl_cnt; ++i)
{
(*stream) << ddl_tab[i]; // DDL
}
(*stream) << OFendl;
}
+ /* reset locale */
+ stream->imbue(oldLocale);
} else {
DCMIMGLE_WARN("can't write curve data, wrong DISPLAY file or GSDF LUT");
}
/*
*
- * Copyright (C) 1996-2024, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
const unsigned long fsize = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns) *
OFstatic_cast(unsigned long, SamplesPerPixel);
- if ((BitsAllocated < 1) || (BitsStored < 1) || (BitsAllocated < BitsStored) ||
- (BitsStored > OFstatic_cast(Uint16, HighBit + 1)))
+ if ((BitsAllocated < 1) || (BitsStored < 1))
{
ImageStatus = EIS_InvalidValue;
- DCMIMGLE_ERROR("invalid values for 'BitsAllocated' (" << BitsAllocated << "), "
- << "'BitsStored' (" << BitsStored << ") and/or 'HighBit' (" << HighBit << ")");
+ DCMIMGLE_ERROR("invalid value(s) for 'BitsAllocated' (" << BitsAllocated << "), "
+ << "and/or 'BitsStored' (" << BitsStored << ")");
+ return;
+ }
+ else if ((BitsAllocated < BitsStored) || (BitsAllocated <= HighBit) || ((BitsStored - 1) > HighBit))
+ {
+ ImageStatus = EIS_InvalidValue;
+ DCMIMGLE_ERROR("invalid combination of values for 'BitsAllocated' (" << BitsAllocated << "), "
+ << "'BitsStored' (" << BitsStored << ") and 'HighBit' (" << HighBit << ")");
return;
}
else if ((evr == EVR_OB) && (BitsStored <= 8))
result = 1;
}
/* delete pixel data */
- delete OFstatic_cast(char *, data); // type cast necessary to avoid compiler warnings using gcc >2.95
+ delete[] OFstatic_cast(char *, data);
}
return result;
}
/*
*
- * Copyright (C) 1996-2021, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcsequen.h"
#include "dcmtk/dcmdata/dcitem.h"
+#include "dcmtk/dcmdata/dcvrobow.h"
#include "dcmtk/dcmdata/dcvrus.h"
+#include "dcmtk/dcmimgle/dibaslut.h"
+#include "dcmtk/dcmimgle/diutils.h"
#include "dcmtk/ofstd/ofbmanip.h"
#include "dcmtk/ofstd/ofcast.h"
OriginalBitsAllocated(16),
OriginalData(NULL)
{
- Uint16 us = 0;
- const DcmElement *descElem = OFreinterpret_cast(const DcmElement *, &descriptor);
- if (DiDocument::getElemValue(descElem, us, 0, OFTrue /*allowSigned*/) >= 3) // number of LUT entries
+ const Uint16 *dataPtr = NULL;
+ const unsigned long count = DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &data), dataPtr);
+ Init(dataPtr, count, descriptor, explanation, descripMode, first, status);
+}
+
+
+DiLookupTable::DiLookupTable(const DcmOtherByteOtherWord &data,
+ const DcmUnsignedShort &descriptor,
+ const DcmLongString *explanation,
+ const EL_BitsPerTableEntry descripMode,
+ const signed long first,
+ EI_Status *status)
+ : DiBaseLUT(),
+ OriginalBitsAllocated(16),
+ OriginalData(NULL)
+{
+ /* check whether we have OW (16 bit data) since OB (8 bit) is not permitted for LUT data */
+ if (data.getVR() == EVR_OW)
{
- Count = (us == 0) ? MAX_TABLE_ENTRY_COUNT : us; // see DICOM supplement 5: "0" => 65536
- DiDocument::getElemValue(descElem, FirstEntry, 1, OFTrue /*allowSigned*/); // can be SS or US (will be typecasted later)
- if ((first >= 0) && (FirstEntry != OFstatic_cast(Uint16, first)))
- {
- DCMIMGLE_WARN("invalid value for 'FirstInputValueMapped' in lookup table ("
- << FirstEntry << ") ... assuming " << first);
- FirstEntry = OFstatic_cast(Uint16, first);
- }
- DiDocument::getElemValue(descElem, us, 2, OFTrue /*allowSigned*/); // bits per entry (only informational)
- unsigned long count = DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &data), Data);
- OriginalData = OFstatic_cast(void *, OFconst_cast(Uint16 *, Data)); // store pointer to original data
- if (explanation != NULL)
- DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, explanation), Explanation); // explanation (free form text)
- checkTable(count, us, descripMode, status);
- } else {
- if (status != NULL)
- {
- *status = EIS_MissingAttribute;
- DCMIMGLE_ERROR("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag());
- } else {
- DCMIMGLE_WARN("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag()
- << " ... ignoring LUT");
- }
- }
+ const Uint16 *dataPtr = NULL;
+ const unsigned long count = DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, &data), dataPtr);
+ Init(dataPtr, count, descriptor, explanation, descripMode, first, status);
+ } else {
+ DCMIMGLE_ERROR("invalid VR for 'LookupTableData' " << data.getTag());
+ *status = EIS_InvalidImage;
+ }
}
Count = (us == 0) ? MAX_TABLE_ENTRY_COUNT : us; // see DICOM supplement 5: "0" => 65536
docu->getValue(descriptor, FirstEntry, 1, item, OFTrue /*allowSigned*/); // can be SS or US (will be typecasted later)
docu->getValue(descriptor, us, 2, item, OFTrue /*allowSigned*/); // bits per entry (only informational)
- unsigned long count = docu->getValue(data, Data, item);
+ const unsigned long count = docu->getValue(data, Data, item);
OriginalData = OFstatic_cast(void *, OFconst_cast(Uint16 *, Data)); // store pointer to original data
if (explanation != DCM_UndefinedTagKey)
docu->getValue(explanation, Explanation, 0 /*vm pos*/, item); // explanation (free form text)
}
+void DiLookupTable::Init(const Uint16 *data,
+ const unsigned long count,
+ const DcmUnsignedShort &descriptor,
+ const DcmLongString *explanation,
+ const EL_BitsPerTableEntry descripMode,
+ const signed long first,
+ EI_Status *status)
+{
+ Uint16 us = 0;
+ const DcmElement *descElem = OFreinterpret_cast(const DcmElement *, &descriptor);
+ if (DiDocument::getElemValue(descElem, us, 0, OFTrue /*allowSigned*/) >= 3) // number of LUT entries
+ {
+ Count = (us == 0) ? MAX_TABLE_ENTRY_COUNT : us; // see DICOM supplement 5: "0" => 65536
+ DiDocument::getElemValue(descElem, FirstEntry, 1, OFTrue /*allowSigned*/); // can be SS or US (will be typecasted later)
+ if ((first >= 0) && (FirstEntry != OFstatic_cast(Uint16, first)))
+ {
+ DCMIMGLE_WARN("invalid value for 'FirstInputValueMapped' in lookup table ("
+ << FirstEntry << ") ... assuming " << first);
+ FirstEntry = OFstatic_cast(Uint16, first);
+ }
+ DiDocument::getElemValue(descElem, us, 2, OFTrue /*allowSigned*/); // bits per entry (only informational)
+ Data = data; // store pointer to passed data
+ OriginalData = OFstatic_cast(void *, OFconst_cast(Uint16 *, Data)); // store pointer to original data
+ if (explanation != NULL)
+ DiDocument::getElemValue(OFreinterpret_cast(const DcmElement *, explanation), Explanation); // explanation (free form text)
+ checkTable(count, us, descripMode, status);
+ } else {
+ if (status != NULL)
+ {
+ *status = EIS_MissingAttribute;
+ DCMIMGLE_ERROR("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag());
+ } else {
+ DCMIMGLE_WARN("incomplete or missing 'LookupTableDescriptor' " << descriptor.getTag()
+ << " ... ignoring LUT");
+ }
+ }
+}
+
+
void DiLookupTable::checkTable(unsigned long count,
Uint16 bits,
const EL_BitsPerTableEntry descripMode,
for (i = Count; i != 0; --i)
{
value = *(p++);
- if (((value >> 8) != 0) && (value & 0xff) != (value >> 8)) // lo-byte not equal to hi-byte and ...
- cmp = 1;
+ if ((value >> 8) != 0) // if hi-byte is not zero
+ {
+ if ((value & 0xff) != (value >> 8)) // lo-byte not equal to hi-byte and ...
+ cmp = 1;
+ }
if (value < MinValue) // get global minimum
MinValue = value;
if (value > MaxValue) // get global maximum
}
+int DiLookupTable::compareLUT(const DcmOtherByteOtherWord &data,
+ const DcmUnsignedShort &descriptor)
+{
+ int result = 1;
+ DiBaseLUT *lut = new DiLookupTable(data, descriptor);
+ if (lut != NULL)
+ result = compare(lut);
+ delete lut;
+ return result;
+}
+
+
int DiLookupTable::compareLUT(const DcmUnsignedShort &data,
const DcmUnsignedShort &descriptor)
{
/*
*
- * Copyright (C) 1996-2024 OFFIS e.V.
+ * Copyright (C) 1996-2025 OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
delete InterData;
delete OutputData;
- delete OFstatic_cast(char *, OverlayData); // type cast necessary to avoid compiler warnings using gcc 2.95
+ delete[] OFstatic_cast(char *, OverlayData);
if (VoiLutData != NULL)
VoiLutData->removeReference(); // only delete if object is no longer referenced
if (PresLutData != NULL)
void DiMonoImage::deleteOverlayData()
{
- delete OFstatic_cast(char *, OverlayData); // type cast necessary to avoid compiler warnings using gcc 2.95
+ delete[] OFstatic_cast(char *, OverlayData);
OverlayData = NULL;
}
data = new Uint32[count]; // allocated memory buffer
if (data != NULL)
{
- Uint32 *q = OFstatic_cast(Uint32 *, data);
- Uint32 value;
+ Uint8 *q = OFstatic_cast(Uint8 *, data);
+ Uint8 value;
Uint16 x;
Uint16 y;
+ int j;
for (y = Rows; y != 0; --y)
{
for (x = Columns; x != 0; --x)
{
value = *(p++); // store gray value
- *(q++) = (value << 16) |
- (value << 8) |
- value; // copy to the three RGB-planes
+ for (j = 3; j != 0; --j)
+ *(q++) = value; // copy to the three RGB-planes
+ *(q++) = 0; // alpha channel is always zero
}
p += nextRow; // jump (backwards) to next row
}
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Example ICC profile data for sRGB color space
+ *
+ */
+
+#ifndef ICCEXAMPLE_H
+#define ICCEXAMPLE_H
+
+// The given ICC profile is a small valid ICC profile for sRGB color space that can be used
+// in case no other profile is available. It is based on the example profile given in
+// https://github.com/saucecontrol/Compact-ICC-Profiles (sRGB-v2-magic.icc using 182-Point Curve)
+
+const unsigned char DCMTK_SRGB_ICC_SAMPLE[] = {
+ 0x00, 0x00, 0x02, 0xe0, 0x6c, 0x63, 0x6d, 0x73, 0x02, 0x10, 0x00, 0x00,
+ 0x73, 0x63, 0x6e, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5a, 0x20,
+ 0x07, 0xe2, 0x00, 0x03, 0x00, 0x14, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x1d,
+ 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
+ 0x73, 0x61, 0x77, 0x73, 0x63, 0x74, 0x72, 0x6c, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d, 0x68, 0x61, 0x6e, 0x64,
+ 0x93, 0xb2, 0x34, 0xa9, 0x0e, 0xb0, 0x22, 0x8a, 0x98, 0xfd, 0x9a, 0xaf,
+ 0xa3, 0x67, 0x89, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x5f,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x0c,
+ 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x14,
+ 0x72, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x14,
+ 0x67, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x00, 0x14,
+ 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x01, 0x78,
+ 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x01, 0x78,
+ 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x01, 0x78,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00,
+ 0x43, 0x43, 0x30, 0x00, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xf3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xc9,
+ 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xa0,
+ 0x00, 0x00, 0x38, 0xf2, 0x00, 0x00, 0x03, 0x8f, 0x58, 0x59, 0x5a, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x96, 0x00, 0x00, 0xb7, 0x89,
+ 0x00, 0x00, 0x18, 0xda, 0x58, 0x59, 0x5a, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x24, 0xa0, 0x00, 0x00, 0x0f, 0x85, 0x00, 0x00, 0xb6, 0xc4,
+ 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6,
+ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x38, 0x00, 0x54, 0x00, 0x70, 0x00, 0x8c,
+ 0x00, 0xa8, 0x00, 0xc4, 0x00, 0xe1, 0x01, 0x00, 0x01, 0x22, 0x01, 0x46,
+ 0x01, 0x6d, 0x01, 0x95, 0x01, 0xc1, 0x01, 0xf0, 0x02, 0x20, 0x02, 0x55,
+ 0x02, 0x8b, 0x02, 0xc4, 0x03, 0x01, 0x03, 0x3f, 0x03, 0x82, 0x03, 0xc6,
+ 0x04, 0x0e, 0x04, 0x59, 0x04, 0xa7, 0x04, 0xf9, 0x05, 0x4c, 0x05, 0xa4,
+ 0x05, 0xfe, 0x06, 0x5c, 0x06, 0xbe, 0x07, 0x21, 0x07, 0x8a, 0x07, 0xf4,
+ 0x08, 0x63, 0x08, 0xd5, 0x09, 0x49, 0x09, 0xc3, 0x0a, 0x3f, 0x0a, 0xbf,
+ 0x0b, 0x42, 0x0b, 0xc9, 0x0c, 0x54, 0x0c, 0xe1, 0x0d, 0x74, 0x0e, 0x09,
+ 0x0e, 0xa2, 0x0f, 0x40, 0x0f, 0xe0, 0x10, 0x85, 0x11, 0x2d, 0x11, 0xda,
+ 0x12, 0x8a, 0x13, 0x3e, 0x13, 0xf6, 0x14, 0xb2, 0x15, 0x71, 0x16, 0x36,
+ 0x16, 0xfd, 0x17, 0xca, 0x18, 0x99, 0x19, 0x6e, 0x1a, 0x46, 0x1b, 0x22,
+ 0x1c, 0x03, 0x1c, 0xe7, 0x1d, 0xd0, 0x1e, 0xbd, 0x1f, 0xae, 0x20, 0xa4,
+ 0x21, 0x9e, 0x22, 0x9c, 0x23, 0x9f, 0x24, 0xa5, 0x25, 0xb1, 0x26, 0xc0,
+ 0x27, 0xd5, 0x28, 0xed, 0x2a, 0x0a, 0x2b, 0x2b, 0x2c, 0x51, 0x2d, 0x7c,
+ 0x2e, 0xaa, 0x2f, 0xde, 0x31, 0x16, 0x32, 0x52, 0x33, 0x94, 0x34, 0xd9,
+ 0x36, 0x24, 0x37, 0x73, 0x38, 0xc6, 0x3a, 0x20, 0x3b, 0x7c, 0x3c, 0xdf,
+ 0x3e, 0x45, 0x3f, 0xb0, 0x41, 0x21, 0x42, 0x96, 0x44, 0x10, 0x45, 0x8f,
+ 0x47, 0x12, 0x48, 0x9b, 0x4a, 0x28, 0x4b, 0xbb, 0x4d, 0x51, 0x4e, 0xee,
+ 0x50, 0x8f, 0x52, 0x35, 0x53, 0xe0, 0x55, 0x90, 0x57, 0x45, 0x59, 0x00,
+ 0x5a, 0xbe, 0x5c, 0x84, 0x5e, 0x4c, 0x60, 0x1b, 0x61, 0xef, 0x63, 0xc7,
+ 0x65, 0xa6, 0x67, 0x89, 0x69, 0x71, 0x6b, 0x5f, 0x6d, 0x51, 0x6f, 0x4a,
+ 0x71, 0x46, 0x73, 0x4a, 0x75, 0x51, 0x77, 0x5e, 0x79, 0x71, 0x7b, 0x88,
+ 0x7d, 0xa6, 0x7f, 0xc8, 0x81, 0xf0, 0x84, 0x1e, 0x86, 0x50, 0x88, 0x89,
+ 0x8a, 0xc5, 0x8d, 0x09, 0x8f, 0x51, 0x91, 0x9f, 0x93, 0xf3, 0x96, 0x4b,
+ 0x98, 0xab, 0x9b, 0x0e, 0x9d, 0x78, 0x9f, 0xe7, 0xa2, 0x5b, 0xa4, 0xd6,
+ 0xa7, 0x56, 0xa9, 0xdb, 0xac, 0x67, 0xae, 0xf7, 0xb1, 0x8f, 0xb4, 0x2a,
+ 0xb6, 0xcc, 0xb9, 0x74, 0xbc, 0x21, 0xbe, 0xd5, 0xc1, 0x8d, 0xc4, 0x4c,
+ 0xc7, 0x10, 0xc9, 0xda, 0xcc, 0xab, 0xcf, 0x7f, 0xd2, 0x5c, 0xd5, 0x3d,
+ 0xd8, 0x24, 0xdb, 0x12, 0xde, 0x04, 0xe0, 0xfe, 0xe3, 0xfc, 0xe7, 0x01,
+ 0xea, 0x0c, 0xed, 0x1c, 0xf0, 0x34, 0xf3, 0x50, 0xf6, 0x73, 0xf9, 0x9b,
+ 0xfc, 0xca, 0xff, 0xff
+};
+
+unsigned int DCMTK_SRGB_ICC_SAMPLE_LEN = 736;
+
+#endif // ICCEXAMPLE_H
/*
*
- * Copyright (C) 2015-2021, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
{
}
+ /** Set whether attribute values should be checked on writing, i.e. if writing
+ * should fail if attribute values violate their VR, VM, character set or value length.
+ * A missing but required value is always considered an error, independent of this setting.
+ * If set to OFFalse, writing will always succeed, even if attribute value constraints
+ * are violated. A warning instead of an error will be printed to the logger.
+ * @param doCheck If OFTrue, attribute value errors are handled as errors on writing, if OFFalse
+ * any errors are ignored.
+ */
+ virtual void setValueCheckOnWrite(const OFBool doCheck)
+ {
+ m_ImagePixel.setValueCheckOnWrite(doCheck);
+ m_GeneralImage.setValueCheckOnWrite(doCheck);
+ DcmIODCommon::setValueCheckOnWrite(doCheck);
+ }
+
virtual void setGeneralImageModuleEnabled(const OFBool enabled)
{
m_GeneralImageModuleEnabled = enabled;
/*
*
- * Copyright (C) 2015-2021, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
*/
virtual ~IODRules();
+ /** Copy constructor, performs deep copy
+ * @param other The other rule set to copy from
+ */
+ IODRules(const IODRules& other);
+
+ /** Assignment operator, performs deep copy
+ * @param other The other rule set to copy from
+ * @return Reference to this object
+ */
+ IODRules& operator=(const IODRules& other);
+
private:
/// Map that holds all rules, accessible by their tag key
OFMap<DcmTagKey, IODRule*> m_Rules;
/*
*
- * Copyright (C) 2015-2019, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmiod/ioddef.h"
#include "dcmtk/oflog/oflog.h"
#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/dcmdata/dcerror.h"
// ----------------------------------------------------------------------------
// Define the loggers for this module
extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidElementValue;
extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidReference;
extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_ReferencesOmitted;
+extern DCMTK_DCMIOD_EXPORT const OFConditionConst IOD_EC_InvalidColorPalette;
/** Class that wraps some constant definitions in the context of IODs
*/
{
public:
+ /** Base class to store pixel data for frames. Right now 8 and 16 bit are supported.
+ * Per default, the class will release memory in the destructor.
+ */
+ struct FrameBase
+ {
+ /// Destructor
+ FrameBase() {}
+ /** Returns pixel data size in bytes
+ * @return Size of pixel data in bytes
+ */
+ virtual size_t getLengthInBytes() const = 0;
+
+ /** Get pointer to pixel data
+ * @return Pointer to pixel data
+ */
+ virtual void* getPixelData() const = 0;
+
+ /** Get bytes used per pixel
+ * @return Bytes per pixel (right now 8 or 16)
+ */
+ virtual Uint8 bytesPerPixel() const = 0;
+
+ /** Get value at given index as 8 bit value
+ * @param byteVal The value at the given index
+ * @param index The index to get the value from
+ * @return EC_Normal if successful, EC_IllegalCall if index is out of bounds
+ */
+ virtual OFCondition getUint8AtIndex(Uint8 &byteVal, const size_t index) const =0;
+
+ /** Get value at given index as 16 bit value
+ * @param shortVal The value at the given index
+ * @param index The index to get the value from
+ * @return EC_Normal if successful, EC_IllegalCall if index is out of bounds
+ */
+ virtual OFCondition getUint16AtIndex(Uint16 &shortVal, const size_t index) const =0;
+
+ /** Set whether Frame class should release memory (default) or whether it will
+ * be released externally.
+ * @param release OFTrue if Frame should release memory, OFFalse otherwise
+ */
+ virtual void setReleaseMemory(OFBool release) = 0;
+
+ /** Print frame data to string (for debugging purposes)
+ * @return String representation of frame data
+ */
+ virtual OFString print() const = 0;
+
+ /** Deconstructor, frees frame data if not disabled via setReleaseMemory() method
+ */
+ virtual ~FrameBase() {}
+ };
+
/** Struct representing a single frame
*/
- struct Frame
+ template<typename PixelType>
+ class Frame : public FrameBase
{
+ public:
+
+ /** Default constructor
+ */
+ Frame() : m_pixData(NULL), m_numPixels(0), m_releaseMemory(OFTrue) {}
+
+ /** Constructor that creates pixel data of the given size (amount of pixels)
+ * @param numPixels Number of pixels to allocate
+ */
+ Frame(const size_t numPixels) : m_pixData(NULL), m_numPixels(numPixels), m_releaseMemory(OFTrue)
+ {
+ m_pixData = new PixelType[numPixels];
+ }
+
+ /** Constructor that takes over pixel data for managing
+ * @param pixelData Pointer to pixel data that is afterwards managed by this class
+ * @param sizeInBytes Size of pixel data in bytes
+ */
+ Frame(PixelType* pixelData, const size_t sizeInBytes) : m_pixData(pixelData), m_numPixels(0), m_releaseMemory(OFTrue)
+ {
+ m_numPixels = sizeInBytes / sizeof(PixelType);
+ }
+
+ /** Copy constructor, copies pixel data
+ * @param rhs Frame to copy
+ */
+ Frame(const Frame& rhs)
+ {
+ delete[] m_pixData;
+ m_pixData = new PixelType[rhs.m_numPixels];
+ memcpy(m_pixData, rhs.m_pixData, rhs.m_numPixels);
+ m_numPixels = rhs.m_numPixels;
+ m_releaseMemory = rhs.m_releaseMemory;
+ };
+
+ /** Assignment constructor, copies pixel data
+ * @param rhs Frame to copy from
+ * @return Reference to this object
+ */
+ Frame& operator=(const Frame& rhs)
+ {
+ if (this != &rhs)
+ {
+ delete[] m_pixData;
+ m_pixData = new PixelType[rhs.m_numPixels];
+ memcpy(m_pixData, rhs.m_pixData, rhs.m_numPixels);
+ m_numPixels = rhs.m_numPixels;
+ m_releaseMemory = rhs.m_releaseMemory;
+ }
+ return *this;
+ }
+
+ /** Set whether pixel data should be release by this class (default)
+ * or is managed externally.
+ * @param release OFTrue if memory should be released, OFFalse otherwise
+ */
+ virtual void setReleaseMemory(OFBool release)
+ {
+ m_releaseMemory = release;
+ }
+
+ /** Get size of pixel data in bytes
+ * @return Size of pixel data in bytes
+ */
+ virtual size_t getLengthInBytes() const
+ {
+ return m_numPixels * bytesPerPixel(); // PixelType is always 1 or 2 bytes
+ }
+
+ /** Returns pointer to pixel data (untyped)
+ * @return Pointer to pixel data
+ */
+ virtual void* getPixelData() const
+ {
+ return m_pixData;
+ }
+
+ /** Returns pointer to pixel data (typed)
+ * @return Pointer to pixel data
+ */
+ virtual PixelType* getPixelDataTyped() const
+ {
+ return m_pixData;
+ }
+
+ /** Returns number of pixels (not necessarily bytes) in the frame
+ * @return Number of pixels
+ */
+ virtual Uint8 bytesPerPixel() const
+ {
+ return sizeof(PixelType);
+ }
+
+ /** Get value at given index as 8 bit value
+ * @param byteVal The value at the given index
+ * @param index The index to get the value from
+ * @return EC_Normal if successful, EC_IllegalCall if index is out of bounds
+ */
+ virtual OFCondition getUint8AtIndex(Uint8 &byteVal, const size_t index) const
+ {
+ if (index >= m_numPixels) {
+ return EC_IllegalCall;
+ }
+ // Since sizeof(PixelType) is known during compile time an
+ // we would require C++11 to mark the condition as constexpr
+ // we disable the related warning in general.
+#include DCMTK_DIAGNOSTIC_PUSH
+#include DCMTK_DIAGNOSTIC_IGNORE_VISUAL_STUDIO_CONSTANT_EXPRESSION_WARNING
+// Add range check for 16-bit to 8-bit conversion
+ if (sizeof(PixelType) == 2 && m_pixData[index] > 255) {
+ DCMIOD_ERROR("Value in the frame is too large to be cast to 8 bits");
+ return EC_IllegalCall;
+ }
+ byteVal = static_cast<Uint8>(m_pixData[index]);
+ return EC_Normal;
+ }
+#include DCMTK_DIAGNOSTIC_POP
+
+ /** Get value at given index as 16 bit value
+ * @param shortVal The value at the given index
+ * @param index The index to get the value from
+ * @return EC_Normal if successful, EC_IllegalCall if index is out of bounds
+ */
+ virtual OFCondition getUint16AtIndex(Uint16 &shortVal, const size_t index) const
+ {
+ if (index >= m_numPixels) {
+ return EC_IllegalCall;
+ }
+ shortVal = static_cast<Uint16>(m_pixData[index]);
+ return EC_Normal;
+ }
+
+ /** Print frame data to string (for debugging purposes)
+ * @return String representation of frame data
+ */
+ virtual OFString print() const
+ {
+ OFStringStream ss;
+ ss << "Frame with " << m_numPixels << " bytes:\n";
+ for (size_t i = 0; i < m_numPixels; i++)
+ {
+ ss << STD_NAMESPACE hex << OFstatic_cast(Uint16, m_pixData[i]) << " ";
+ }
+ ss << "\n";
+ return ss.str().c_str();
+ }
+
/// Array for the pixel data bytes
- Uint8* pixData;
- /// Number of pixel data bytes (i.e.\ Bits Allocated)
- size_t length;
- /// Destructor, frees memory
+ PixelType* m_pixData;
+ /// Number of pixels in the frame
+ size_t m_numPixels;
+ // Denote whether to release memory in destructor
+ OFBool m_releaseMemory;
+
+ /** Destructor, frees memory if not disabled via setReleaseMemory() method
+ */
~Frame()
{
- delete[] pixData;
- pixData = NULL;
+ if (m_releaseMemory)
+ {
+ delete[] m_pixData;
+ m_pixData = NULL;
+ }
}
};
~DcmIODTypes() {};
};
+
#endif // IODTYPES_H
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
* (Would be 'const' if the methods from 'dcmdata' would also
* be 'const')
* @param delem DICOM element that is set to a copy of the dataset's
- * orinal element
+ * original element
* @param rule Rule describing parameters to be checked on element.
* @return EC_Normal if element could be retrieved and value is correct, an
* error code otherwise
container.clear();
}
+
+ /** Deletes all elements from given map and calls "delete" on each
+ * of them to clear memory.
+ * @param container The map that should be cleared. Must contain
+ * pointers to objects that are allocated on the heap.
+ */
+ template <class Map>
+ static void freeMap(Map& container)
+ {
+ typename Map::iterator it = container.begin();
+ while (it != container.end())
+ {
+ delete (*it).second;
+ it++;
+ }
+ container.clear();
+ }
+
/** Clones and copies all elements from source to destination container by
* copy constructing all elements.
* If copying fails (because memory is exhausted), EC_MemoryExhausted is returned
return 0;
}
+ /** Set the current date and time on the given module by using setContentDate()
+ * and setContentTime() methods. The current date and time is retrieved
+ * from the system clock.
+ * @param module The module to set the date and time on
+ * @return EC_Normal if successful, an error code otherwise
+ */
template <typename ModuleType>
static OFCondition setContentDateAndTimeNow(ModuleType& module)
{
static OFCondition extractBinaryFrames(Uint8* pixData,
const size_t numFrames,
const size_t bitsPerFrame,
- OFVector<DcmIODTypes::Frame*>& results);
+ OFVector<DcmIODTypes::FrameBase*>& results);
/** Resets the given condition to EC_Normal if checkValue is true and
* prints a related message as a warning to the debug logger.
*/
static void resetConditionIfCheckDisabled(OFCondition& result, const OFBool checkValue, DcmElement& elem);
+
+ /** If checkValue is true, the given OFCondition for certain errors (listed below), prints
+ * a debug message if the condition is not good, and resets the condition
+ * to EC_Normal. If checkValue is false, the method does nothing.
+ * The following error codes are handled, i.e. reset:
+ * EC_ValueRepresentationViolated
+ * EC_MaximumLengthViolated
+ * EC_InvalidCharacter
+ * EC_ValueMultiplicityViolated
+ * @param result The condition to check. Only EC_ValueRepresentationViolated, EC_MaximumLengthViolated,
+ * EC_InvalidCharacter and EC_ValueMultiplicityViolated are handled.
+ * @param checkValue If this value is true, the listed condition are reset to EC_Normal; otherwise the
+ * condition is not changed and no message is printed.
+ * @param elem Used if the condition is reset to EC_Normal to print a message in case of a "reset"
+ */
+ static void resetValueCheckResult(OFCondition& result, const OFBool checkValue, DcmElement& elem);
+
private:
// We only have static functions so we do not need an instance of
// this class so far.
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
* An attribute is considered belonging to the module if there are rules
* marked as belonging to this module via the rule's module name.
*/
- void clearData();
+ virtual void clearData();
/** Set missing values by inventing "default values". Automatically
* called during write() in IODComponent. In this bas class implementation,
/*
*
- * Copyright (C) 2015-2019, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
*/
virtual OFCondition getSoftwareVersions(OFString& value, const signed long pos = 0) const;
+ /** Get a copy altogether as EquipmentInfo
+ * @return EquipmentInfo object containing all relevant information
+ * If some data is not available, it will contain an empty string
+ */
+ virtual IODGeneralEquipmentModule::EquipmentInfo getEquipmentInfo() const;
+
/** Set Manufacturer
* @param value Value to be set (single value only) or "" for no value
* @param checkValue Check 'value' for conformance with VR (LO) and VM (1)
/*
*
- * Copyright (C) 2015-2019, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
virtual OFCondition setIrradiationEventUID(const OFString& value, const OFBool checkValue = OFTrue);
private:
- /// The module's name ("GeneralIamgeModule")
+ /// The module's name ("GeneralImageModule")
static const OFString m_ModuleName;
};
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Class for managing the ICC Profile Module
+ *
+ */
+
+#ifndef MODICCPROFILE_H
+#define MODICCPROFILE_H
+
+#include "dcmtk/config/osconfig.h"
+
+#include "dcmtk/dcmiod/iodrules.h"
+#include "dcmtk/dcmiod/modbase.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/ofstd/oftypes.h"
+
+/** Class representing the ICC Profile Module:
+ *
+ * ICC Profile (0028,2000): (OB, 1, 1)
+ * Color Space (0028,2002): (CS, 3, 1)
+ */
+class DCMTK_DCMIOD_EXPORT IODICCProfileModule : public IODModule
+{
+
+public:
+
+ /** Constructor
+ * @param item The item to be used for data storage. If NULL, the
+ * class creates an empty data container.
+ * @param rules The rule set for this class. If NULL, the class creates
+ * one from scratch and adds its values.
+ */
+ IODICCProfileModule(OFshared_ptr<DcmItem> item, OFshared_ptr<IODRules> rules);
+
+ /** Constructor
+ */
+ IODICCProfileModule();
+
+ /** Destructor
+ */
+ virtual ~IODICCProfileModule();
+
+ /** Clear all attributes from the data that are handled by this module.
+ * An attribute is considered belonging to the module if there are rules
+ * marked as belonging to this module via the rule's module name.
+ */
+ virtual void clearData();
+
+ /** Resets rules to their original values
+ */
+ virtual void resetRules();
+
+ /** Get name of module
+ * @return Name of the module ("ICCProfileModule")
+ */
+ virtual OFString getName() const;
+
+ /** Read attributes from given item into this class
+ * @param source The source to read from
+ * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise
+ * old data is overwritten (or amended)
+ * @result EC_Normal if reading was successful, error otherwise
+ */
+ virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue);
+
+ /** Write attributes from this class into given item
+ * @param destination The item to write to
+ * @result EC_Normal if writing was successful, error otherwise
+ */
+ virtual OFCondition write(DcmItem& destination);
+
+ /** Get the ICC Color Profile data
+ * @param value Returns a reference to the icc profile data
+ * @param numBytes Number of bytes in the icc profile data returned in value parameter
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getICCProfile(const Uint8*& value, Uint32& numBytes);
+
+ /** Get Color Space
+ * @param value Reference to variable in which a copy of the value should be stored
+ * @param pos Index of the value to get (0..vm-1), -1 for all components
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getColorSpace(OFString& value, const signed long pos = 0) const;
+
+ /** Set ICC Profile data
+ * @param value The value of ICC Profile (will be copied)
+ * @param numBytes Number of bytes in the icc profile data (value parameter)
+ * @param checkValue Check value for conformance with VR (OB) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition
+ setICCProfile(const Uint8* value, const unsigned long numBytes, const OFBool checkValue = OFTrue);
+
+ /** Set default ICC Profile data (SRGB)
+ * @param setColorSpaceDescription If OFTrue, Color Space Description (0028,2004)
+ * is set to "SRGB" when setting the default profile. If not, this attribute
+ * is not touched by this method (i.e. by default it remains unset).
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setDefaultProfile(const OFBool& setColorSpaceDescription = OFTrue);
+
+ /** Set Color Space
+ * @param value The value of Color Space
+ * @param checkValue Check value for conformance with VR (CS) and VM (1) if enabled
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setColorSpace(const OFString& value, const OFBool checkValue = OFTrue);
+
+private:
+
+ /// The module's name ("ICCProfileModule")
+ static const OFString m_ModuleName;
+
+};
+
+#endif // MODICCPROFILE_H
/*
*
- * Copyright (C) 2016-2019, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
return pBase->read(dataset);
return IOD_EC_InvalidPixelData;
}
+
+ /** Set whether attribute values should be checked on writing, i.e. if writing
+ * should fail if attribute values violate their VR, VM, character set or value length.
+ * A missing but required value is always considered an error, independent of this setting.
+ * If set to OFFalse, writing will always succeed, even if attribute value constraints
+ * are violated. A warning instead of an error will be printed to the logger.
+ * @param doCheck If OFTrue, attribute value errors are handled as errors on writing, if OFFalse
+ * any errors are ignored.
+ */
+ void setValueCheckOnWrite(const OFBool doCheck)
+ {
+ if (IODImagePixelBase* pBase = OFvisit<IODImagePixelBase*>(IODImagePixelVariantBaseVisitor(), *this))
+ pBase->setValueCheckOnWrite(doCheck);
+ }
};
#endif // MODIMAGEPIXELBASE_H
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Class for managing the Palette Color Lookup Table Module
+ *
+ */
+
+#ifndef MODPALETTECOLORLUT_H
+#define MODPALETTECOLORLUT_H
+
+#include "dcmtk/config/osconfig.h"
+
+#include "dcmtk/dcmdata/dctagkey.h"
+#include "dcmtk/ofstd/ofmem.h"
+#include "dcmtk/dcmiod/iodrules.h"
+#include "dcmtk/dcmiod/modbase.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/ofstd/oftypes.h"
+
+/** Class representing the Palette Color Lookup Table Module:
+ *
+ * Red Palette Color Lookup Table Descriptor (0028,1101): (US or SS, 3, 1)
+ * Green Palette Color Lookup Table Descriptor (0028,1102): (US or SS, 3, 1)
+ * Blue Palette Color Lookup Table Descriptor (0028,1103): (US or SS, 3, 1)
+ * Palette Color Lookup Table UID (0028,1199): (UI, 1, 3)
+ * Red Palette Color Lookup Table Data (0028,1201): (OW, 1-n, 1C)
+ * Green Palette Color Lookup Table Data (0028,1202): (OW, 1-n, 1C)
+ * Blue Palette Color Lookup Table Data (0028,1203): (OW, 1-n, 1C)
+ * Segmented Red Palette Color Lookup Table Data (0028,1221): (OW, 1-n, 1C)
+ * Segmented Green Palette Color Lookup Table Data (0028,1222): (OW, 1-n, 1C)
+ * Segmented Blue Palette Color Lookup Table Data (0028,1223): (OW, 1-n, 1C)
+ */
+class DCMTK_DCMIOD_EXPORT IODPaletteColorLUTModule : public IODModule
+{
+
+public:
+ /** Constructor
+ * @param item The item to be used for data storage. If NULL, the
+ * class creates an empty data container.
+ * @param rules The rule set for this class. If NULL, the class creates
+ * one from scratch and adds its values.
+ */
+ IODPaletteColorLUTModule(OFshared_ptr<DcmItem> item, OFshared_ptr<IODRules> rules);
+
+ /** Constructor
+ */
+ IODPaletteColorLUTModule();
+
+ /** Destructor
+ */
+ virtual ~IODPaletteColorLUTModule();
+
+ /** Clear all attributes from the data that are handled by this module.
+ * An attribute is considered belonging to the module if there are rules
+ * marked as belonging to this module via the rule's module name.
+ */
+ virtual void clearData();
+
+ /** Resets rules to their original values
+ */
+ virtual void resetRules();
+
+ /** Get name of module
+ * @return Name of the module ("PaletteColorLookupTableModule")
+ */
+ virtual OFString getName() const;
+
+ /** Read attributes from given item into this class
+ * @param source The source to read from
+ * @param clearOldData If OFTrue, old data is cleared before reading. Otherwise
+ * old data is overwritten (or amended)
+ * @result EC_Normal if reading was successful, error otherwise
+ */
+ virtual OFCondition read(DcmItem& source, const OFBool clearOldData = OFTrue);
+
+ /** Write attributes from this class into given item
+ * @param destination The item to write to
+ * @result EC_Normal if writing was successful, error otherwise
+ */
+ virtual OFCondition write(DcmItem& destination);
+
+ // ---------------- Getters -----------------------------
+
+ /** Returns the number of bits used per LUT data entry.
+ * If the number of bits is not the same for all LUTs, 0 is returned, indicating an error.
+ * @return The number of bits used per LUT data entry (8 or 16)
+ */
+ virtual Uint8 numBits();
+
+ /** Get the Red Palette Color Lookup Table Descriptor
+ * @param value The value of Red Palette Color Lookup Table Descriptor
+ * @param pos The position of the value to be retrieved (0..2)
+ * @return EC_Normal if value is found, an error code otherwise
+ */
+ virtual OFCondition getRedPaletteColorLookupTableDescriptor(Uint16& value, const unsigned long pos = 0) const;
+
+ /** Get the Green Palette Color Lookup Table Descriptor
+ * @param value The value of Green Palette Color Lookup Table Descriptor
+ * @param pos The position of the value to be retrieved (0..2)
+ * @return EC_Normal if value is found, an error code otherwise
+ */
+ virtual OFCondition getGreenPaletteColorLookupTableDescriptor(Uint16& value, const unsigned long pos = 0) const;
+
+ /** Get the Blue Palette Color Lookup Table Descriptor
+ * @param value The value of Blue Palette Color Lookup Table Descriptor
+ * @param pos The position of the value to be retrieved (0..2)
+ * @return EC_Normal if value is found, an error code otherwise
+ */
+ virtual OFCondition getBluePaletteColorLookupTableDescriptor(Uint16& value, const unsigned long pos = 0) const;
+
+ /** Get the Palette Color Lookup Table UID
+ * @param value Reference to variable in which the value should be stored
+ * @param pos Index of the value to get (0..vm-1), -1 for all components
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getPaletteColorLookupTableUID(OFString& value, const signed long pos = 0) const;
+
+ /** Get the Red Palette Color Lookup Table Data (16 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getRedPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Red Palette Color Lookup Table Data (8 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getRedPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Green Palette Color Lookup Table Data (16 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual
+ OFCondition getGreenPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Green Palette Color Lookup Table Data (8 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual
+ OFCondition getGreenPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Blue Palette Color Lookup Table Data (16 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual
+ OFCondition getBluePaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries);
+
+
+ /** Get the Blue Palette Color Lookup Table Data (8 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual
+ OFCondition getBluePaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries);
+
+
+ /** Get the Segmented Red Palette Color Lookup Table Data
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getSegmentedRedPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Segmented Red Palette Color Lookup Table Data (8 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getSegmentedRedPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Segmented Green Palette Color Lookup Table Data (16 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getSegmentedGreenPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Segmented Green Palette Color Lookup Table Data (8 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getSegmentedGreenPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Segmented Blue Palette Color Lookup Table Data (16 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getSegmentedBluePaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries);
+
+ /** Get the Segmented Blue Palette Color Lookup Table Data (8 bit version)
+ * @param dataCopy Reference to variable in which a copy of the value should be stored
+ * @param numEntries Number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getSegmentedBluePaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries);
+
+ // ---------------- Setters -----------------------------
+
+ /** Set the Red Palette Color Lookup Table Descriptor
+ * @param value The value of Red Palette Color Lookup Table Descriptor
+ * @param pos The position of the value to be set (0..2)
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setRedPaletteColorLookupTableDescriptor(const Uint16& value, const unsigned long pos = 0);
+
+ /** Set the Green Palette Color Lookup Table Descriptor
+ * @param value The value of Green Palette Color Lookup Table Descriptor
+ * @param pos The position of the value to be set (0..2)
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setGreenPaletteColorLookupTableDescriptor(const Uint16& value, const unsigned long pos = 0);
+
+ /** Set the Blue Palette Color Lookup Table Descriptor
+ * @param value The value of Blue Palette Color Lookup Table Descriptor
+ * @param pos The position of the value to be set (0..2)
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setBluePaletteColorLookupTableDescriptor(const Uint16& value, const unsigned long pos = 0);
+
+ /** Set the Palette Color Lookup Table UID
+ * @param value The value of Palette Color Lookup Table UID
+ * @param checkValue Check value for conformance with VR (UI) and VM (1) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setPaletteColorLookupTableUID(const OFString& value, const OFBool checkValue = OFTrue);
+
+ /** Set the Red Palette Color Lookup Table Data (16 bit version)
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition
+ setRedPaletteColorLookupTableData(const Uint16* value, const unsigned long numEntries, const OFBool checkValue = OFTrue);
+
+ /** Set the Red Palette Color Lookup Table Data (8 bit version)
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition
+ setRedPaletteColorLookupTableData(const Uint8* value, const unsigned long numEntries, const OFBool checkValue = OFTrue);
+
+
+ /** Set the Green Palette Color Lookup Table Data (16 bit version)
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+
+ virtual OFCondition
+ setGreenPaletteColorLookupTableData(const Uint16* value, const unsigned long numEntries, const OFBool checkValue = OFTrue);
+
+ /** Set the Green Palette Color Lookup Table Data (8 bit version)
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+
+ virtual OFCondition
+ setGreenPaletteColorLookupTableData(const Uint8* value, const unsigned long numEntries, const OFBool checkValue = OFTrue);
+
+ /** Set the Blue Palette Color Lookup Table Data (16 bit version)
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition
+ setBluePaletteColorLookupTableData(const Uint16* value, const unsigned long numEntries, const OFBool checkValue = OFTrue);
+
+ /** Set the Blue Palette Color Lookup Table Data (8 bit version).
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition
+ setBluePaletteColorLookupTableData(const Uint8* value, const unsigned long numEntries, const OFBool checkValue = OFTrue);
+
+ /** Set the Segmented Red Palette Color Lookup Table Data (16 bit version).
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setSegmentedRedPaletteColorLookupTableData(const Uint16* value,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+ /** Set the Segmented Red Palette Color Lookup Table Data (8 bit version).
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setSegmentedRedPaletteColorLookupTableData(const Uint8* value,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+ /** Set the Segmented Green Palette Color Lookup Table Data (16 bit version).
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setSegmentedGreenPaletteColorLookupTableData(const Uint16* value,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+ /** Set the Segmented Green Palette Color Lookup Table Data (8 bit version)
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setSegmentedGreenPaletteColorLookupTableData(const Uint8* value,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+ /** Set the Segmented Blue Palette Color Lookup Table Data (16 bit version).
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setSegmentedBluePaletteColorLookupTableData(const Uint16* value,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+ /** Set the Segmented Blue Palette Color Lookup Table Data (8 bit version).
+ * @param value The value of Red Palette Color Lookup Table Data
+ * @param numEntries Number of entries in the lookup table
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setSegmentedBluePaletteColorLookupTableData(const Uint8* value,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+ // ---------------- Convenience Setters -----------------------------
+
+ /** Set the Palette Color Lookup Table Data (red, green, blue, 8 or 16 bit).
+ * @tparam T The data type of the color lookup table data. (Uint16 or Uint8)
+ * @param copyRed The value of Red Palette Color Lookup Table Data
+ * @param copyGreen The value of Green Palette Color Lookup Table Data
+ * @param copyBlue The value of Blue Palette Color Lookup Table Data
+ * @param numEntries Number of entries in each of the lookup tables
+ * @param checkValue Check value for conformance with VR (OW) and VM (1-n) if OFTrue
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ template <typename T> OFCondition setPaletteColorLookupTableData(const T* copyRed,
+ const T* copyGreen,
+ const T* copyBlue,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+
+ /** Sets the red, green, and blue data for a segmented palette color lookup table.
+ * The data arrays for red, green, and blue should be of type T and have a length of numEntries.
+ * \tparam T The data type of the color lookup table data. (Uint16 or Uint8)
+ * \param copyRedData Pointer to the array containing the red data.
+ * \param copyGreenData Pointer to the array containing the green data.
+ * \param copyBlueData Pointer to the array containing the blue data.
+ * \param numEntries The number of entries in the lookup table.
+ * \param checkValue Flag indicating whether to check the input values for validity. Default is true.
+ * \return EC_Normal if successful, error otherwise.
+ */
+ template <typename T> OFCondition setSegmentedPaletteColorLookupTableData(const T* copyRedData,
+ const T* copyGreenData,
+ const T* copyBlueData,
+ const unsigned long numEntries,
+ const OFBool checkValue = OFTrue);
+
+ /** Sets all three values of the Red Palette Color Lookup Table Descriptor.
+ * @param numEntries The number of entries in the lookup table.
+ * @param firstValueMapped The first value mapped in the lookup table.
+ * @param numBitsPerEntry The number of bits per entry in the lookup table.
+ *
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setRedPaletteColorLookupTableDescriptor(const Uint16 numEntries,
+ const Uint16 firstValueMapped,
+ const Uint8 numBitsPerEntry);
+
+ /** Sets all three values of the Green Palette Color Lookup Table Descriptor.
+ * @param numEntries The number of entries in the lookup table.
+ * @param firstValueMapped The first value mapped in the lookup table.
+ * @param numBitsPerEntry The number of bits per entry in the lookup table.
+ *
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setGreenPaletteColorLookupTableDescriptor(const Uint16 numEntries,
+ const Uint16 firstValueMapped,
+ const Uint8 numBitsPerEntry);
+
+ /** Sets the blue Palette Color Lookup Table Descriptor.
+ * @param numEntries The number of entries in the lookup table.
+ * @param firstValueMapped The first value mapped in the lookup table.
+ * @param numBitsPerEntry The number of bits per entry in the lookup table.
+ *
+ * @return EC_Normal if value is set, an error code otherwise
+ */
+ virtual OFCondition setBluePaletteColorLookupTableDescriptor(const Uint16 numEntries,
+ const Uint16 firstValueMapped,
+ const Uint8 numBitsPerEntry);
+
+protected:
+
+ /** Returns a copy of the data for the given tag. A copy of the data is returned into the given
+ * pointer and the number of entries is returned.
+ * @param dataTag The tag of the data to be copied (i.e. Red/Green/Blue/PaletteColorLookupTableData)
+ * @param lutData The pointer that will be set to the copied data
+ * @param num8BitEntries The number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getUint8DataCopy(const DcmTagKey& dataTag, const Uint8*& lutData, unsigned long& num8BitEntries);
+
+ /** Put the given 8 bit data into the given tag.
+ * @param dataTag The tag of the data to be copied into (i.e. Red/Green/Blue/PaletteColorLookupTableData)
+ * @param lutData The data to be copied
+ * @param num8BitEntries The number of entries in the lookup table
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition putUint8Data(const DcmTagKey& dataTag, const Uint8* lutData, const unsigned long num8BitEntries);
+
+ /** Returns a 16 bit copy of the data for the given tag. The data is returned into the given
+ * pointer and the number of entries is returned.
+ * @param dataTag The tag of the data to be copied to (i.e. Red/Green/Blue/PaletteColorLookupTableData)
+ * @param lutData The pointer that will be set to the copied data
+ * @param numEntries The number of entries in the data
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getUint16DataCopy(const DcmTagKey& dataTag, const Uint16*& lutData, unsigned long& numEntries);
+
+ /** Returns a reference of the data from the given tag and the number of entries in the data
+ * @param dataTag The tag of the data to be copied to (i.e. Red/Green/Blue/PaletteColorLookupTableData)
+ * @param lutData The pointer that will be set to the data
+ * @param numEntries The number of entries in the data
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getUint16Data(const DcmTagKey& dataTag, const Uint16*& lutData, unsigned long& numEntries);
+
+ /** Check given LUT for consistency with descriptor.
+ * @param descriptorTag The tag of the descriptor to be checked (i.e. Red/Green/BluePaletteColorLookupTableDescriptor)
+ * @param dataTag The tag of the data to be checked (i.e. Red/Green/BluePaletteColorLookupTableData).
+ * Should of course match the descriptor "color".
+ * @return OFTrue if LUT is consistent, OFFalse otherwise
+ */
+ virtual OFBool checkLUT(const DcmTagKey& descriptorTag,
+ const DcmTagKey& dataTag);
+
+ /** Check basic consistency rules of all palette descriptors (not their data).
+ * @param isError If OFTrue, errors are reported, otherwise warnings
+ * @return OFTrue if all descriptors are consistent, OFFalse otherwise
+ */
+ virtual OFBool checkDescriptorConsistency(const OFBool& isError);
+
+ /** Check basic consistency of all palette data with their descriptors.
+ * @param isError If OFTrue, errors are reported, otherwise warnings
+ * @return OFTrue if all data is consistent, OFFalse otherwise
+ */
+ virtual OFBool checkDataConsistency(const OFBool& isError);
+
+ /** Check that either segmented or unsegmented LUT data is used, not both.
+ * @param isError If OFTrue, errors are reported, otherwise warnings
+ * @param isSegmented Returns OFTrue if segmented LUT data is used, OFFalse otherwise
+ * @return OFTrue if LUT data is consistent, OFFalse otherwise
+ */
+ virtual OFBool checkSegmentConsistency(const OFBool& isError, OFBool& isSegmented);
+
+ /** Report error/warning for given descriptor tag.
+ * @param descriptorTag The tag of the descriptor to be reported (i.e. Red/Green/BluePaletteColorLookupTableDescriptor)
+ * @param message The message to be reported
+ * @param isError If OFTrue, an error is reported, otherwise a warning
+ */
+ virtual void reportLUTError(const DcmTagKey& descriptorTag,
+ const OFString& message,
+ const OFBool& isError);
+
+ /** Get number of LUT data entries for given descriptor tag.
+ * @param dataTag The tag of the data to be checked (i.e. Red/Green/BluePaletteColorLookupTableDescriptor)
+ * @param result The number of entries in the data
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition numEntriesForData(const DcmTagKey& dataTag, Uint16& result);
+
+private:
+
+ /// The module's name ("PaletteColorLookupTableModule")
+ static const OFString m_ModuleName;
+
+};
+
+#endif // MODPALETTECOLORLUT_H
modgeneralseries.cc
modgeneralstudy.cc
modhelp.cc
+ modiccprofile.cc
modimagepixel.cc
modimagepixelbase.cc
modmultiframefg.cc
modmultiframedimension.cc
+ modpalettecolorlut.cc
modpatient.cc
modpatientstudy.cc
modsegmentationseries.cc
modusfor.cc
)
-DCMTK_TARGET_LINK_MODULES(dcmiod dcmdata ofstd oflog)
+DCMTK_TARGET_LINK_MODULES(dcmiod dcmimgle dcmdata ofstd oflog)
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
- ../include/dcmtk/dcmiod/ioddef.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
- ../include/dcmtk/dcmiod/ioddef.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
- ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/iodutil.h \
- ../include/dcmtk/dcmiod/iodrules.h \
+ ../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../include/dcmtk/dcmiod/iodutil.h ../include/dcmtk/dcmiod/iodrules.h \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def
iodutil.o: iodutil.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmiod/iodutil.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../include/dcmtk/dcmiod/iodutil.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
- ../include/dcmtk/dcmiod/ioddef.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
- ../include/dcmtk/dcmiod/ioddef.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
- ../include/dcmtk/dcmiod/ioddef.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h
modfor.o: modfor.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
- ../include/dcmtk/dcmiod/ioddef.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h
+modiccprofile.o: modiccprofile.cc \
+ ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../include/dcmtk/dcmiod/modiccprofile.h \
+ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../include/dcmtk/dcmiod/modbase.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../include/dcmtk/dcmiod/iodutil.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdate.h \
+ ../../ofstd/include/dcmtk/ofstd/oftime.h \
+ ../include/dcmtk/dcmiod/iccexample.h
modimagepixel.o: modimagepixel.cc \
../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmiod/modimagepixel.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../include/dcmtk/dcmiod/iodutil.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h
+modpalettecolorlut.o: modpalettecolorlut.cc \
+ ../../config/include/dcmtk/config/osconfig.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../include/dcmtk/dcmiod/modbase.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../include/dcmtk/dcmiod/iodrules.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
+ ../include/dcmtk/dcmiod/iodutil.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdate.h \
+ ../../ofstd/include/dcmtk/ofstd/oftime.h \
+ ../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
+ ../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \
+ ../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \
+ ../../dcmimgle/include/dcmtk/dcmimgle/diobjcou.h
modpatient.o: modpatient.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../include/dcmtk/dcmiod/iodutil.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../include/dcmtk/dcmiod/ioddef.h ../include/dcmtk/dcmiod/iodrules.h \
../include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
ofstddir = $(top_srcdir)/../ofstd
oflogdir = $(top_srcdir)/../oflog
dcmdatadir = $(top_srcdir)/../dcmdata
+dcmimgledir = $(top_srcdir)/../dcmimgle
-LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include -I$(dcmdatadir)/include
+LOCALINCLUDES = -I$(ofstddir)/include -I$(oflogdir)/include -I$(dcmdatadir)/include -I$(dcmimgledir)/include
LOCALDEFS =
modfloatingpointimagepixel.o modfor.o modgeneralimage.o modgeneralseries.o \
modgeneralstudy.o modhelp.o modimagepixelbase.o modimagepixel.o modmultiframedimension.o \
modmultiframefg.o modpatient.o modpatientstudy.o modsegmentationseries.o modsopcommon.o \
- modsynchronization.o modusfor.o
+ modsynchronization.o modusfor.o modiccprofile.o modpalettecolorlut.o
library = libdcmiod.$(LIBEXT)
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
{
// reset element rules
resetRules();
- set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion);
+ // We don't check the value here, since this is a convenience constructor and we
+ // cannot return an error code anyway
+ set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion, OFFalse /* checkValue */);
}
OFCondition CodeSequenceMacro::check(const bool /* quiet */)
{
// reset element rules
resetRules();
- set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion);
+ // We don't check the value here, since this is a convenience constructor and we
+ // cannot return an error code anyway
+ set(codeValue, codingSchemeDesignator, codeMeaning, codingSchemeVersion, OFFalse /* checkValue */);
}
OFString CodeSequenceMacro::getName() const
{
if (!refFramesOrSegments.empty())
{
- if (sopClassUID == UID_SegmentationStorage)
+ if ( (sopClassUID == UID_SegmentationStorage)
+ || (sopClassUID == UID_LabelMapSegmentationStorage)
+ || (sopClassUID == UID_SurfaceSegmentationStorage)
+ || (sopClassUID == UID_HeightMapSegmentationStorage) )
{
cond = result->setReferencedSegmentNumber(refFramesOrSegments);
}
, m_IODRules()
{
resetRules();
- setInstanceNumber(instanceNumber);
- setContentLabel(contentLabel);
- setContentDescription(contentDescription);
- setContentCreatorName(contentCreatorName);
+ setInstanceNumber(instanceNumber, OFFalse /* do not check value */);
+ setContentLabel(contentLabel, OFFalse /* do not check value */);
+ setContentDescription(contentDescription, OFFalse /* do not check value */);
+ setContentCreatorName(contentCreatorName, OFFalse /* do not check value */);
}
void ContentIdentificationMacro::resetRules()
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
IODRules* newRules = new IODRules();
if (newRules)
{
- OFMap<DcmTagKey, IODRule*>::iterator it = m_Rules.begin();
- while (it != m_Rules.end())
+ *newRules = *this;
+ }
+ else
+ {
+ DCMIOD_WARN("Cannot create new IODRules, memory exhausted?");
+ }
+ return newRules;
+}
+
+// Copy constructor
+IODRules::IODRules(const IODRules& other)
+ : m_Rules()
+{
+ // use assignment operator
+ *this = other;
+}
+
+// Assignment operator (deep copy)
+IODRules& IODRules::operator=(const IODRules& other)
+{
+ if (this != &other)
+ {
+ clear(); // Clear existing rules
+ // Perform deep copy of all rules
+ OFMap<DcmTagKey, IODRule*>::const_iterator it = other.m_Rules.begin();
+ while (it != other.m_Rules.end())
{
- if (it->second)
+ IODRule* newRule = it->second->clone();
+ if (newRule)
{
- IODRule* newRule = it->second->clone();
- if (newRule)
- {
- newRules->addRule(newRule);
- }
- else
- {
- DCMIOD_WARN("Cannot create new IODRule, memory exhausted?");
- }
+ m_Rules.insert(OFMake_pair(it->first, newRule));
}
else
{
- DCMIOD_WARN("Found NULL IODRule, cannot clone");
+ DCMIOD_WARN("Cannot create new IODRule, memory exhausted?");
}
- it++;
+ ++it;
}
}
- else
- {
- DCMIOD_WARN("Cannot create new IODRules, memory exhausted?");
- }
- return newRules;
+ return *this;
}
IODRule* IODRules::getByTag(const DcmTagKey& key) const
IODRules::iterator it = m_Rules.begin();
while (it != m_Rules.end())
{
- out << (*it).first << ": Type \"" << (*it).second->getType() << "\", VM \"" << (*it).second->getType() << "\""
+ out << (*it).first << ": Type \"" << (*it).second->getType() << "\", VM \"" << (*it).second->getType() << "\" Component: " << (*it).second->getModule()
<< OFendl;
it++;
}
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
makeOFConditionConst(IOD_EC_InvalidReference, OFM_dcmiod, 12, OF_error, "One or more invalid SOP references");
makeOFConditionConst(
IOD_EC_ReferencesOmitted, OFM_dcmiod, 13, OF_error, "One or more SOP references have been omitted");
+makeOFConditionConst(IOD_EC_InvalidColorPalette, OFM_dcmiod, 14, OF_error, "Invalid Color Palette LUT");
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmiod/iodutil.h"
#include "dcmtk/dcmdata/dctypes.h" // logger
#include "dcmtk/dcmiod/iodrules.h"
-
+#include "dcmtk/dcmiod/iodtypes.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcdicent.h"
#include "dcmtk/dcmdata/dcdict.h"
#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/dcmdata/dcvrda.h"
#include "dcmtk/dcmdata/dcvrtm.h"
-#include "dcmtk/dcmiod/iodtypes.h"
#include "dcmtk/ofstd/ofstring.h"
// --- static helpers ---
result,
rule->getModule().c_str(),
logLevel);
- resetConditionIfCheckDisabled(result, checkValue, *delem);
+ resetValueCheckResult(result, checkValue, *delem);
}
if (result.good())
{
OFCondition DcmIODUtil::extractBinaryFrames(Uint8* pixData,
const size_t numFrames,
const size_t bitsPerFrame,
- OFVector<DcmIODTypes::Frame*>& results)
+ OFVector<DcmIODTypes::FrameBase*>& results)
{
if (pixData == NULL)
{
return EC_MemoryExhausted;
}
memset(frameData, 0, bytesPerFrame); // Initialize to 0
- DcmIODTypes::Frame* frame = new DcmIODTypes::Frame();
+ DcmIODTypes::Frame<Uint8>* frame = new DcmIODTypes::Frame<Uint8>();
if (frame == NULL)
{
DCMIOD_ERROR("Memory exhausted while extracting frames");
delete[] frameData;
return EC_MemoryExhausted;
}
- frame->pixData = frameData;
- frame->length = bytesPerFrame;
+ frame->m_pixData = frameData;
+ frame->m_numPixels = bytesPerFrame;
results.push_back(frame);
}
Uint8 bit = (pixData[inputByteIndex] >> (8 - bitsLeftInInputByte)) & 0x01;
// Set bit in current frame to to position calculated from bitsLeftInTargetByte
- results[targetFrameIndex]->pixData[targetByteIndex] |= (bit << (8 - bitsLeftInTargetByte));
+ OFstatic_cast(Uint8*, results[targetFrameIndex]->getPixelData())[targetByteIndex] |= (bit << (8 - bitsLeftInTargetByte));
// Move to next bit
bitsLeftInInputByte--;
}
}
}
+
+
+void DcmIODUtil::resetValueCheckResult(OFCondition& result, const OFBool checkValue, DcmElement& elem)
+{
+ if (!checkValue)
+ {
+ if ( (result == EC_ValueRepresentationViolated) ||
+ (result == EC_MaximumLengthViolated) ||
+ (result == EC_InvalidCharacter) ||
+ (result == EC_ValueMultiplicityViolated) )
+ {
+ // print element to string
+ OFOStringStream oss;
+ oss << elem.getTag() << " " << DcmVR(elem.getVR()).getVRName() << " ";
+ oss << DcmTag(elem.getTag()).getTagName() << " ";
+ if (elem.getLength() > 1024)
+ {
+ oss << "(value too long for printing)";
+ }
+ {
+ OFString val;
+ elem.getOFString(val, 0, OFTrue);
+ oss << "[" << val << "]";
+ }
+
+ DCMIOD_DEBUG("Ignoring error (" << result.text() <<") when checking element: " << oss.str().c_str());
+ result = EC_Normal;
+ }
+ }
+}
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
return DcmIODUtil::getStringValueFromItem(DCM_SoftwareVersions, *m_Item, value, pos);
}
+IODGeneralEquipmentModule::EquipmentInfo IODGeneralEquipmentModule::getEquipmentInfo() const
+{
+ EquipmentInfo info;
+ getManufacturer(info.m_Manufacturer);
+ getManufacturerModelName(info.m_ManufacturerModelName);
+ getDeviceSerialNumber(info.m_DeviceSerialNumber);
+ getSoftwareVersions(info.m_SoftwareVersions);
+ return info;
+}
+
OFCondition IODGeneralEquipmentModule::setDeviceSerialNumber(const OFString& value, const OFBool checkValue)
{
OFCondition result = (checkValue) ? DcmLongString::checkStringValue(value, "1") : EC_Normal;
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
DCM_RETIRED_OtherPatientIDs,
DCM_OtherPatientIDsSequence,
DCM_OtherPatientNames,
- DCM_EthnicGroup,
+ DCM_RETIRED_EthnicGroup,
DCM_PatientComments,
DCM_PatientSpeciesDescription,
DCM_PatientSpeciesCodeSequence,
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Class for managing the ICC Profile Module
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/ofstd/ofcast.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/dcmdata/dcerror.h"
+#include "dcmtk/dcmdata/dcvrobow.h"
+#include "dcmtk/dcmdata/dcvrcs.h"
+#include "dcmtk/dcmiod/modiccprofile.h"
+#include "dcmtk/dcmiod/iodutil.h"
+#include "dcmtk/dcmiod/iodrules.h"
+#include "dcmtk/dcmiod/iccexample.h"
+
+const OFString IODICCProfileModule::m_ModuleName = "ICCProfileModule";
+
+IODICCProfileModule::IODICCProfileModule(OFshared_ptr<DcmItem> item, OFshared_ptr<IODRules> rules)
+ : IODModule(item, rules)
+{
+ // reset element rules
+ resetRules();
+}
+
+IODICCProfileModule::IODICCProfileModule()
+ : IODModule()
+{
+ resetRules();
+}
+
+
+IODICCProfileModule::~IODICCProfileModule()
+{
+ // nothing to do
+}
+
+void IODICCProfileModule::resetRules()
+{
+ m_Rules->addRule(new IODRule(DCM_ICCProfile, "1", "1", getName(), DcmIODTypes::IE_IMAGE),OFTrue);
+ m_Rules->addRule(new IODRule(DCM_ColorSpace, "1", "3", getName(), DcmIODTypes::IE_IMAGE),OFTrue);
+}
+
+void IODICCProfileModule::clearData()
+{
+ IODModule::clearData();
+}
+
+OFString IODICCProfileModule::getName() const
+{
+ return m_ModuleName;
+}
+
+OFCondition IODICCProfileModule::read(DcmItem& source, const OFBool clearOldData)
+{
+ if (clearOldData)
+ clearData();
+
+ IODComponent::read(source, OFFalse /* data already cleared */);
+ return EC_Normal;
+}
+
+OFCondition IODICCProfileModule::write(DcmItem& destination)
+{
+ return IODComponent::write(destination);
+}
+
+// --- get() functionality ---
+
+OFCondition IODICCProfileModule::getICCProfile(const Uint8*& value, Uint32& numBytes)
+{
+ DcmElement* elem = NULL;
+ OFCondition result = DcmIODUtil::getAndCheckElementFromDataset(*m_Item, elem, getRules()->getByTag(DCM_ICCProfile));
+ if (result.good())
+ {
+ if (elem->ident() == EVR_OB)
+
+ {
+ Uint8* val = NULL;
+ result = OFstatic_cast(DcmOtherByteOtherWord*, elem)->getUint8Array(val);
+ if (result.good())
+ {
+ // detach value pointer and set numBytes
+ value = val;
+ numBytes = elem->getLength();
+ elem->detachValueField();
+ }
+ }
+ else
+ {
+ result = EC_InvalidVR;
+ }
+ }
+ delete elem; // clean up, we copied the value already
+ return result;
+}
+
+OFCondition IODICCProfileModule::getColorSpace(OFString& value, const signed long pos) const
+{
+ return DcmIODUtil::getStringValueFromItem(DCM_ColorSpace, *m_Item, value, pos);
+}
+
+// --- set() functionality ---
+
+OFCondition IODICCProfileModule::setICCProfile(const Uint8* value, const unsigned long numBytes, const OFBool /* not used */)
+{
+ return m_Item->putAndInsertUint8Array(DCM_ICCProfile, value, numBytes);
+}
+
+OFCondition IODICCProfileModule::setDefaultProfile(const OFBool& setColorSpaceDescription)
+{
+ OFCondition result = setICCProfile(DCMTK_SRGB_ICC_SAMPLE, DCMTK_SRGB_ICC_SAMPLE_LEN, OFFalse /* do not check, we expect this is valid */);
+ if (result.good() && setColorSpaceDescription)
+ {
+ result = setColorSpace("SRGB", OFFalse /* do not check, we expect this is valid */);
+ }
+ return result;
+}
+
+OFCondition IODICCProfileModule::setColorSpace(const OFString& value, const OFBool checkValue)
+{
+ OFCondition result;
+ IODRule* rule = getRules()->getByTag(DCM_ColorSpace);
+ if (rule)
+ {
+ result = (checkValue) ? DcmCodeString::checkStringValue(value, rule->getVM()) : EC_Normal;
+ if (result.good()) result = m_Item->putAndInsertOFStringArray(DCM_ColorSpace, value);
+ }
+ else
+ {
+ result = IOD_EC_NoSuchRule;
+ }
+ return result;
+}
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
: IODModule()
, m_DimensionIndexSequence()
, m_DimensionOrganizationSequence()
+ , m_CheckOnWrite(OFTrue)
{
resetRules();
}
DcmSequenceOfItems* perFrame = NULL;
if (fgItem->findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, perFrame).bad())
{
- DCMIOD_WARN(
- "Will not check dimension consistency with functional groups (no per-frame functional groups found)");
+ DCMIOD_DEBUG(
+ "Omitting dimension consistency check with functional groups (Per-frame FGs not yet present)");
}
OFCondition result;
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Class for managing the Palette Color LUT Module
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/dcmdata/dcelem.h"
+#include "dcmtk/dcmdata/dcerror.h"
+#include "dcmtk/dcmdata/dcvrobow.h"
+#include "dcmtk/dcmdata/dcvrui.h"
+#include "dcmtk/dcmiod/iodtypes.h"
+#include "dcmtk/dcmiod/modbase.h"
+#include "dcmtk/dcmiod/modpalettecolorlut.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/dcmdata/dcvrus.h"
+#include "dcmtk/dcmiod/iodutil.h"
+#include "dcmtk/dcmimgle/diluptab.h"
+#include "dcmtk/ofstd/ofmem.h"
+#include "dcmtk/ofstd/oftypes.h"
+
+const OFString IODPaletteColorLUTModule::m_ModuleName = "PaletteColorLookupTableModule";
+
+IODPaletteColorLUTModule::IODPaletteColorLUTModule(OFshared_ptr<DcmItem> item, OFshared_ptr<IODRules> rules)
+ : IODModule(item, rules)
+{
+ // reset element rules
+ resetRules();
+}
+
+IODPaletteColorLUTModule::IODPaletteColorLUTModule()
+ : IODModule()
+{
+ resetRules();
+}
+
+
+IODPaletteColorLUTModule::~IODPaletteColorLUTModule()
+{
+ // nothing to do
+}
+
+void IODPaletteColorLUTModule::resetRules()
+{
+ m_Rules->addRule(new IODRule(DCM_RedPaletteColorLookupTableDescriptor, "3", "1", getName(), DcmIODTypes::IE_IMAGE),
+ OFTrue);
+ m_Rules->addRule(
+ new IODRule(DCM_GreenPaletteColorLookupTableDescriptor, "3", "1", getName(), DcmIODTypes::IE_IMAGE), OFTrue);
+ m_Rules->addRule(new IODRule(DCM_BluePaletteColorLookupTableDescriptor, "3", "1", getName(), DcmIODTypes::IE_IMAGE),
+ OFTrue);
+ m_Rules->addRule(new IODRule(DCM_PaletteColorLookupTableUID, "1", "3", getName(), DcmIODTypes::IE_IMAGE), OFTrue);
+ m_Rules->addRule(new IODRule(DCM_RedPaletteColorLookupTableData, "1", "1C", getName(), DcmIODTypes::IE_IMAGE),
+ OFTrue);
+ m_Rules->addRule(new IODRule(DCM_GreenPaletteColorLookupTableData, "1", "1C", getName(), DcmIODTypes::IE_IMAGE),
+ OFTrue);
+ m_Rules->addRule(new IODRule(DCM_BluePaletteColorLookupTableData, "1", "1C", getName(), DcmIODTypes::IE_IMAGE),
+ OFTrue);
+ m_Rules->addRule(
+ new IODRule(DCM_SegmentedRedPaletteColorLookupTableData, "1", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue);
+ m_Rules->addRule(
+ new IODRule(DCM_SegmentedGreenPaletteColorLookupTableData, "1", "1C", getName(), DcmIODTypes::IE_IMAGE),
+ OFTrue);
+ m_Rules->addRule(
+ new IODRule(DCM_SegmentedBluePaletteColorLookupTableData, "1", "1C", getName(), DcmIODTypes::IE_IMAGE), OFTrue);
+}
+
+void IODPaletteColorLUTModule::clearData()
+{
+ IODModule::clearData();
+}
+
+OFString IODPaletteColorLUTModule::getName() const
+{
+ return m_ModuleName;
+}
+
+OFCondition IODPaletteColorLUTModule::read(DcmItem& source, const OFBool clearOldData)
+{
+ if (clearOldData)
+ clearData();
+
+ IODComponent::read(source, OFFalse /* data already cleared */);
+ OFBool isSegmented;
+ checkSegmentConsistency(OFFalse, isSegmented);
+ if (!isSegmented)
+ {
+ checkLUT(DCM_RedPaletteColorLookupTableDescriptor, DCM_RedPaletteColorLookupTableData);
+ checkLUT(DCM_GreenPaletteColorLookupTableDescriptor, DCM_GreenPaletteColorLookupTableData);
+ checkLUT(DCM_BluePaletteColorLookupTableDescriptor, DCM_BluePaletteColorLookupTableData);
+ checkDescriptorConsistency(OFFalse /* only warn */);
+ checkDataConsistency(OFFalse /* only warn */);
+ }
+ return EC_Normal;
+}
+
+OFCondition IODPaletteColorLUTModule::write(DcmItem& destination)
+{
+ OFBool valid, isSegmented;
+ valid = checkSegmentConsistency(OFFalse, isSegmented);
+ if (valid)
+ {
+ if (!isSegmented)
+ {
+ valid = checkLUT(DCM_RedPaletteColorLookupTableDescriptor, DCM_RedPaletteColorLookupTableData);
+ if (valid)
+ valid = checkLUT(DCM_GreenPaletteColorLookupTableDescriptor, DCM_GreenPaletteColorLookupTableData);
+ if (valid)
+ valid = checkLUT(DCM_BluePaletteColorLookupTableDescriptor, DCM_BluePaletteColorLookupTableData);
+ if (valid)
+ valid = checkDescriptorConsistency(OFTrue /* report as errors */);
+ if (valid)
+ valid = checkDataConsistency(OFTrue /* report as errors */);
+ if (valid)
+ {
+ return IODComponent::write(destination);
+ }
+ else
+ {
+ return IOD_EC_InvalidColorPalette;
+ }
+ }
+ else
+ {
+ return IODComponent::write(destination);
+ }
+ }
+
+ return IOD_EC_InvalidColorPalette;
+}
+
+OFCondition IODPaletteColorLUTModule::getRedPaletteColorLookupTableDescriptor(Uint16& value,
+ const unsigned long pos) const
+{
+ OFCondition result = m_Item->findAndGetUint16(DCM_RedPaletteColorLookupTableDescriptor, value, pos);
+ return result;
+}
+
+OFCondition IODPaletteColorLUTModule::getGreenPaletteColorLookupTableDescriptor(Uint16& value,
+ const unsigned long pos) const
+{
+ OFCondition result = m_Item->findAndGetUint16(DCM_GreenPaletteColorLookupTableDescriptor, value, pos);
+ return result;
+}
+
+OFCondition IODPaletteColorLUTModule::getBluePaletteColorLookupTableDescriptor(Uint16& value,
+ const unsigned long pos) const
+{
+ OFCondition result = m_Item->findAndGetUint16(DCM_BluePaletteColorLookupTableDescriptor, value, pos);
+ return result;
+}
+
+
+OFCondition IODPaletteColorLUTModule::getPaletteColorLookupTableUID(OFString& value, const signed long pos) const
+{
+ return DcmIODUtil::getStringValueFromItem(DCM_PaletteColorLookupTableUID, *m_Item, value, pos);
+}
+
+OFCondition IODPaletteColorLUTModule::getRedPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries)
+{
+ return getUint16DataCopy(DCM_RedPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getGreenPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries)
+{
+ return getUint16DataCopy(DCM_GreenPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getBluePaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries)
+{
+ return getUint16DataCopy(DCM_BluePaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getSegmentedRedPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries)
+{
+ return getUint16DataCopy(DCM_SegmentedRedPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getSegmentedGreenPaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries)
+{
+ return getUint16DataCopy(DCM_SegmentedGreenPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getSegmentedBluePaletteColorLookupTableData(const Uint16*& dataCopy, unsigned long& numEntries)
+{
+ return getUint16DataCopy(DCM_SegmentedBluePaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+// 8 bit versions for LUT data access
+
+OFCondition IODPaletteColorLUTModule::getRedPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries)
+{
+ return getUint8DataCopy(DCM_RedPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getGreenPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries)
+{
+ return getUint8DataCopy(DCM_GreenPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getBluePaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries)
+{
+ return getUint8DataCopy(DCM_BluePaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getSegmentedRedPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries)
+{
+ return getUint8DataCopy(DCM_SegmentedRedPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getSegmentedGreenPaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries)
+{
+ return getUint8DataCopy(DCM_SegmentedGreenPaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+OFCondition IODPaletteColorLUTModule::getSegmentedBluePaletteColorLookupTableData(const Uint8*& dataCopy, unsigned long& numEntries)
+{
+ return getUint8DataCopy(DCM_SegmentedBluePaletteColorLookupTableData, dataCopy, numEntries);
+}
+
+// -------------------- set() --------------------
+
+OFCondition IODPaletteColorLUTModule::setRedPaletteColorLookupTableDescriptor(const Uint16& value,
+ const unsigned long pos)
+{
+ OFCondition result = m_Item->putAndInsertUint16(DCM_RedPaletteColorLookupTableDescriptor, value, pos);
+ return result;
+}
+
+
+OFCondition IODPaletteColorLUTModule::setGreenPaletteColorLookupTableDescriptor(const Uint16& value,
+ const unsigned long pos)
+{
+ return m_Item->putAndInsertUint16(DCM_GreenPaletteColorLookupTableDescriptor, value, pos);
+}
+
+
+OFCondition IODPaletteColorLUTModule::setBluePaletteColorLookupTableDescriptor(const Uint16& value,
+ const unsigned long pos)
+{
+ return m_Item->putAndInsertUint16(DCM_BluePaletteColorLookupTableDescriptor, value, pos);
+}
+
+
+OFCondition IODPaletteColorLUTModule::setPaletteColorLookupTableUID(const OFString& value, const OFBool checkValue)
+{
+ OFCondition result = (checkValue) ? DcmUniqueIdentifier::checkStringValue(value, "1") : EC_Normal;
+ if (result.good()) result = m_Item->putAndInsertOFStringArray(DCM_PaletteColorLookupTableUID, value);
+ return result;
+}
+
+OFCondition IODPaletteColorLUTModule::setRedPaletteColorLookupTableData(const Uint16* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 8))
+ {
+ DCMIOD_ERROR("Cannot set 16 bit data for 8 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long fixZero = numEntries;
+ if (numEntries == 0)
+ {
+ fixZero = 65536;
+ }
+ return m_Item->putAndInsertUint16Array(DCM_RedPaletteColorLookupTableData, data, fixZero);
+}
+
+OFCondition IODPaletteColorLUTModule::setGreenPaletteColorLookupTableData(const Uint16* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 8))
+ {
+ DCMIOD_ERROR("Cannot set 16 bit data for 8 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long fixZero = numEntries;
+ if (numEntries == 0)
+ {
+ fixZero = 65536;
+ }
+ return m_Item->putAndInsertUint16Array(DCM_GreenPaletteColorLookupTableData, data, fixZero);
+}
+
+OFCondition IODPaletteColorLUTModule::setBluePaletteColorLookupTableData(const Uint16* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 8))
+ {
+ DCMIOD_ERROR("Cannot set 16 bit data for 8 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 65536;
+ }
+ return m_Item->putAndInsertUint16Array(DCM_BluePaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setRedPaletteColorLookupTableData(const Uint8* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 16))
+ {
+ DCMIOD_ERROR("Cannot set 8 bit data for 16 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 256;
+ }
+ return putUint8Data(DCM_RedPaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setGreenPaletteColorLookupTableData(const Uint8* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 16))
+ {
+ DCMIOD_ERROR("Cannot set 8 bit data for 16 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 256;
+ }
+ return putUint8Data(DCM_GreenPaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setBluePaletteColorLookupTableData(const Uint8* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 16))
+ {
+ DCMIOD_ERROR("Cannot set 8 bit data for 16 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 256;
+ }
+ return putUint8Data(DCM_BluePaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setSegmentedRedPaletteColorLookupTableData(const Uint16* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 8))
+ {
+ DCMIOD_ERROR("Cannot set 16 bit data for 8 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 65536;
+ }
+ return m_Item->putAndInsertUint16Array(DCM_SegmentedRedPaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setSegmentedGreenPaletteColorLookupTableData(const Uint16* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 8))
+ {
+ DCMIOD_ERROR("Cannot set 16 bit data for 8 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 65536;
+ }
+ return m_Item->putAndInsertUint16Array(DCM_SegmentedGreenPaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setSegmentedBluePaletteColorLookupTableData(const Uint16* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 8))
+ {
+ DCMIOD_ERROR("Cannot set 16 bit data for 8 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 65536;
+ }
+ return m_Item->putAndInsertUint16Array(DCM_SegmentedBluePaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setSegmentedRedPaletteColorLookupTableData(const Uint8* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 16))
+ {
+ DCMIOD_ERROR("Cannot set 8 bit data for 16 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 256;
+ }
+ return putUint8Data(DCM_SegmentedRedPaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setSegmentedGreenPaletteColorLookupTableData(const Uint8* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 16))
+ {
+ DCMIOD_ERROR("Cannot set 8 bit data for 16 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 256;
+ }
+ return putUint8Data(DCM_SegmentedGreenPaletteColorLookupTableData, data, zeroFix);
+}
+
+OFCondition IODPaletteColorLUTModule::setSegmentedBluePaletteColorLookupTableData(const Uint8* data,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ if (checkValue && (numBits() == 16))
+ {
+ DCMIOD_ERROR("Cannot set 8 bit data for 16 bit LUT");
+ return IOD_EC_InvalidColorPalette;
+ }
+ unsigned long zeroFix = numEntries;
+ if (numEntries == 0)
+ {
+ zeroFix = 256;
+ }
+ return putUint8Data(DCM_SegmentedBluePaletteColorLookupTableData, data, zeroFix);
+}
+
+
+template<typename T>
+OFCondition IODPaletteColorLUTModule::setPaletteColorLookupTableData(const T* redData,
+ const T* greenData,
+ const T* blueData,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ OFCondition result = setRedPaletteColorLookupTableData(redData, numEntries, checkValue);
+ if (result.good()) result = setGreenPaletteColorLookupTableData(greenData, numEntries, checkValue);
+ if (result.good()) result = setBluePaletteColorLookupTableData(blueData, numEntries, checkValue);
+ return result;
+}
+
+template<typename T>
+OFCondition IODPaletteColorLUTModule::setSegmentedPaletteColorLookupTableData(const T* redData,
+ const T* greenData,
+ const T* blueData,
+ const unsigned long numEntries,
+ const OFBool checkValue)
+{
+ OFCondition result = setSegmentedRedPaletteColorLookupTableData(redData, numEntries, checkValue);
+ if (result.good()) result = setSegmentedGreenPaletteColorLookupTableData(greenData, numEntries, checkValue);
+ if (result.good()) result = setSegmentedBluePaletteColorLookupTableData(blueData, numEntries, checkValue);
+ return result;
+}
+
+OFCondition IODPaletteColorLUTModule::setRedPaletteColorLookupTableDescriptor(const Uint16 numEntries,
+ const Uint16 firstMapped,
+ const Uint8 bitsPerEntry)
+{
+ // TODO Check value
+ OFCondition result;
+ Uint16 values[3];
+ values[0] = numEntries;
+ values[1] = firstMapped;
+ values[2] = bitsPerEntry;
+
+ return m_Item->putAndInsertUint16Array(DCM_RedPaletteColorLookupTableDescriptor, values, 3);
+}
+
+
+OFCondition IODPaletteColorLUTModule::setGreenPaletteColorLookupTableDescriptor(const Uint16 numEntries,
+ const Uint16 firstMapped,
+ const Uint8 bitsPerEntry)
+{
+ // TODO check value
+ OFCondition result;
+ Uint16 values[3];
+ values[0] = numEntries;
+ values[1] = firstMapped;
+ values[2] = bitsPerEntry;
+ return m_Item->putAndInsertUint16Array(DCM_GreenPaletteColorLookupTableDescriptor, values, 3);
+}
+
+
+
+OFCondition IODPaletteColorLUTModule::setBluePaletteColorLookupTableDescriptor(const Uint16 numEntries,
+ const Uint16 firstMapped,
+ const Uint8 bitsPerEntry)
+{
+ OFCondition result;
+ Uint16 values[3];
+ values[0] = numEntries;
+ values[1] = firstMapped;
+ values[2] = bitsPerEntry;
+
+ return m_Item->putAndInsertUint16Array(DCM_BluePaletteColorLookupTableDescriptor, values, 3);
+}
+
+
+OFBool IODPaletteColorLUTModule::checkLUT(const DcmTagKey& descriptorTag,
+ const DcmTagKey& dataTag)
+{
+ DcmElement* data = NULL;
+ DcmElement* descriptor = NULL;
+ m_Item->findAndGetElement(dataTag, data);
+ m_Item->findAndGetElement(descriptorTag, descriptor);
+ if (!data || !descriptor)
+ {
+ reportLUTError(descriptorTag, "Palette Color LUT Data or Descriptor missing", OFFalse /* warning */);
+ return OFFalse;
+ }
+ // LUT Data always OW in this module, LUT Descriptor is always US or SS
+ if ( (data->getTag().getEVR() != EVR_OW) || ( (descriptor->getTag().getEVR() != EVR_US) && (descriptor->getTag().getEVR() != EVR_SS)) )
+ {
+ reportLUTError(descriptorTag, "Palette Color LUT Data or Descriptor have invalid VR", OFFalse /* warning */);
+ return OFFalse;
+ }
+ DiLookupTable lut(*OFstatic_cast(DcmOtherByteOtherWord*, data), *OFstatic_cast(DcmUnsignedShort*, descriptor), NULL, ELM_CheckValue);
+ if (!lut.isValid())
+ {
+ reportLUTError(descriptorTag, "Palette Color LUT Data is invalid", OFFalse /* warning */);
+ return OFFalse;
+ }
+ return OFTrue;
+}
+
+
+void IODPaletteColorLUTModule::reportLUTError(const DcmTagKey& tag, const OFString& message, const OFBool& warning)
+{
+ OFString color;
+ if (tag == DCM_RedPaletteColorLookupTableDescriptor)
+ color = "Red";
+ else if (tag == DCM_GreenPaletteColorLookupTableDescriptor)
+ color = "Green";
+ else if (tag == DCM_BluePaletteColorLookupTableDescriptor)
+ color = "Blue";
+ if (warning)
+ DCMIOD_WARN(color << " " << message);
+ else
+ DCMIOD_ERROR(color << " " << message);
+}
+
+Uint8 IODPaletteColorLUTModule::numBits()
+{
+ OFCondition result;
+ Uint16 numBitsR = 0;
+ Uint16 numBitsG = 0;
+ Uint16 numBitsB = 0;
+ if (getRedPaletteColorLookupTableDescriptor(numBitsR, 2).good() && getGreenPaletteColorLookupTableDescriptor(numBitsG, 2).good() && getBluePaletteColorLookupTableDescriptor(numBitsB, 2).good())
+ {
+ if ((numBitsR != numBitsG) || (numBitsR != numBitsB) || (numBitsG != numBitsB))
+ {
+ DCMIOD_WARN("Bits per entry in Red, Green and Blue Palette Color LUT Descriptor are not equal");
+ return 0;
+ }
+ }
+ else
+ {
+ DCMIOD_WARN("Could not read bits per entry in Red, Green or Blue Palette Color LUT Descriptor");
+ return 0;
+ }
+ if ((numBitsR != 8) && (numBitsR != 16))
+ {
+ DCMIOD_WARN("Bits per entry in Red, Green and Blue Palette Color LUT Descriptor are greater than 16");
+ return 0;
+ }
+ return OFstatic_cast(Uint8, numBitsR);
+}
+
+
+OFBool IODPaletteColorLUTModule::checkDescriptorConsistency(const OFBool& isError)
+{
+ // Check whether all 2nd values ("first value mapped") have same value.
+ Uint16 redFirstMapped = 0;
+ Uint16 greenFirstMapped = 0;
+ Uint16 blueFirstMapped = 0;
+ Sint32 r,g,b;
+ r=g=b=0;
+ if (getRedPaletteColorLookupTableDescriptor(redFirstMapped, 1).good())
+ {
+ if (getGreenPaletteColorLookupTableDescriptor(greenFirstMapped, 1).good())
+ {
+ if (getBluePaletteColorLookupTableDescriptor(blueFirstMapped, 1).good())
+ {
+ r = redFirstMapped;
+ g = greenFirstMapped;
+ b = blueFirstMapped;
+ if ( (r != g) || (r != b) || (g != b) )
+ {
+ if (isError)
+ {
+ DCMIOD_ERROR("First value mapped in Red, Green and Blue Palette Color LUT Descriptor are not equal");
+ }
+ else
+ {
+ DCMIOD_WARN("First value mapped in Red, Green and Blue Palette Color LUT Descriptor are not equal");
+ }
+ return OFFalse;
+ }
+ Uint16 lastRed, lastGreen, lastBlue;
+ lastRed = lastGreen = lastBlue = 0;
+ if (getRedPaletteColorLookupTableDescriptor(lastRed, 2).good() && getGreenPaletteColorLookupTableDescriptor(lastGreen, 2).good() && getBluePaletteColorLookupTableDescriptor(lastBlue, 2).good())
+ {
+ if (lastRed != lastGreen || lastRed != lastBlue || lastGreen != lastBlue)
+ {
+ if (isError)
+ {
+ DCMIOD_ERROR("Bits per entry in Red, Green and Blue Palette Color LUT Descriptor are not equal");
+ }
+ else
+ {
+ DCMIOD_WARN("Bits per entry in Red, Green and Blue Palette Color LUT Descriptor are not equal");
+ }
+ return OFFalse;
+ }
+ return OFTrue;
+ }
+ }
+ }
+ }
+ if (isError)
+ {
+ DCMIOD_ERROR("Could not read first value mapped in Red, Green or Blue Palette Color LUT Descriptor");
+ }
+ else
+ {
+ DCMIOD_WARN("Could not read first value mapped in Red, Green or Blue Palette Color LUT Descriptor");
+ }
+ return OFFalse;
+}
+
+
+OFBool IODPaletteColorLUTModule::checkDataConsistency(const OFBool& isError)
+{
+ // Check whether all 2nd values ("first value mapped") have same value.
+ Uint16 redFirstMapped, greenFirstMapped, blueFirstMapped, redNumEntries, greenNumEntries, blueNumEntries;
+ unsigned long redActualNumEntries, greenActualNumEntries, blueActualNumEntries;
+ redFirstMapped = greenFirstMapped = blueFirstMapped = redNumEntries = greenNumEntries = blueNumEntries = 0;
+ redActualNumEntries = greenActualNumEntries = blueActualNumEntries = 0;
+ const Uint8 bits = numBits();
+ OFCondition result;
+ OFString message;
+ result = getRedPaletteColorLookupTableDescriptor(redFirstMapped, 1);
+ if (result.good())
+ {
+ result = getGreenPaletteColorLookupTableDescriptor(greenFirstMapped, 1);
+ }
+ if (result.good())
+ {
+ result = getBluePaletteColorLookupTableDescriptor(blueFirstMapped, 1);
+ }
+ if (result.bad())
+ {
+ message = "Could not read first value mapped in Red, Green or Blue Palette Color LUT Descriptor";
+ }
+
+ if (result.good())
+ {
+ if (getRedPaletteColorLookupTableDescriptor(redNumEntries, 0).good())
+ {
+ if (getGreenPaletteColorLookupTableDescriptor(greenNumEntries, 0).good())
+ {
+ if (getBluePaletteColorLookupTableDescriptor(blueNumEntries, 0).good())
+ {
+ unsigned long maxEntries = 0;
+ if (bits == 8)
+ {
+ maxEntries = 256;
+ const Uint8* data = NULL;
+ result = getRedPaletteColorLookupTableData(data, redActualNumEntries);
+ delete[] data;
+ if (result.good())
+ {
+ result = getGreenPaletteColorLookupTableData(data, greenActualNumEntries);
+ delete[] data;
+ }
+ if (result.good())
+ {
+ result = getBluePaletteColorLookupTableData(data, blueActualNumEntries);
+ delete[] data;
+ }
+ }
+ else if (bits == 16)
+ {
+ maxEntries = 65536;
+ const Uint16* data = NULL;
+ result = getRedPaletteColorLookupTableData(data, redActualNumEntries);
+ delete[] data;
+ if (result.good())
+ {
+ result = getGreenPaletteColorLookupTableData(data, greenActualNumEntries);
+ delete[] data;
+ }
+ if (result.good())
+ {
+ result = getBluePaletteColorLookupTableData(data, blueActualNumEntries);
+ delete[] data;
+ }
+ }
+ if (result.good())
+ {
+ if ( (redNumEntries != redActualNumEntries) || (greenNumEntries != greenActualNumEntries) || (blueNumEntries != blueActualNumEntries) )
+ {
+ // also check special case where number descriptor entries is 0 (i.e. max value)
+ if ( (!redNumEntries && (redActualNumEntries != maxEntries)) || (!greenNumEntries && (greenActualNumEntries != maxEntries)) || (!blueNumEntries && (blueActualNumEntries != maxEntries)) )
+ {
+ message = "Number of entries in Red, Green and Blue Palette Color LUT Data does not match descriptor";
+ }
+ }
+ return OFTrue;
+ }
+ }
+ }
+ }
+ }
+ if (isError)
+ {
+ DCMIOD_ERROR(message);
+ }
+ else
+ {
+ DCMIOD_WARN(message);
+ }
+ return OFFalse;
+}
+
+
+OFBool IODPaletteColorLUTModule::checkSegmentConsistency(const OFBool& isError, OFBool& isSegmented)
+{
+ // Check that unsegmented LUTs are used together with segmented LUTs
+ isSegmented = OFFalse;
+ OFBool hasNonSegmentedLUTs = OFFalse;
+ OFString msg;
+ // Check for segmented LUT descriptors
+ if (m_Item->tagExists(DCM_SegmentedRedPaletteColorLookupTableData) && m_Item->tagExists(DCM_SegmentedGreenPaletteColorLookupTableData) && m_Item->tagExists(DCM_SegmentedBluePaletteColorLookupTableData))
+ {
+ // Also check for segmented LUT data
+ if (m_Item->tagExists(DCM_SegmentedRedPaletteColorLookupTableData) && m_Item->tagExists(DCM_SegmentedGreenPaletteColorLookupTableData) && m_Item->tagExists(DCM_SegmentedBluePaletteColorLookupTableData))
+ {
+ isSegmented = OFTrue;
+ }
+ }
+ // Check for unsegmented LUT descriptors
+ if (m_Item->tagExists(DCM_RedPaletteColorLookupTableDescriptor) || m_Item->tagExists(DCM_GreenPaletteColorLookupTableDescriptor) || m_Item->tagExists(DCM_BluePaletteColorLookupTableDescriptor))
+ {
+ // Check for unsegmented LUT data
+ if (m_Item->tagExists(DCM_RedPaletteColorLookupTableData) || m_Item->tagExists(DCM_GreenPaletteColorLookupTableData) || m_Item->tagExists(DCM_BluePaletteColorLookupTableData))
+ {
+ hasNonSegmentedLUTs = OFTrue;
+ }
+ }
+ // Check that both are not used together
+ if (isSegmented && hasNonSegmentedLUTs)
+ {
+ msg = "Segmented Palette LUT attributes are used together with Unsegmented LUT attributes";
+ }
+ if (!isSegmented && !hasNonSegmentedLUTs)
+ {
+ msg = "No or incomplete Palette LUT attributes found";
+ }
+ if (msg.length() > 0)
+ {
+ if (isError)
+ {
+ DCMIOD_ERROR(msg);
+ }
+ else
+ {
+ DCMIOD_WARN(msg);
+ }
+ return OFFalse;
+ }
+ return OFTrue;
+}
+
+
+OFCondition IODPaletteColorLUTModule::getUint8DataCopy(const DcmTagKey& dataTag, const Uint8*& lutData, unsigned long& num8BitEntries)
+{
+ OFCondition result = EC_Normal;
+ num8BitEntries = 0;
+
+ const Uint16* data = NULL;
+ unsigned long num16BitEntries = 0;
+ // check first whether we actually have 8 bit data by checking third descriptor value
+ if (numBits() != 8)
+ {
+ DCMIOD_ERROR("Cannot convert 16 bit data to 8 bit data: Descriptor does not indicate 8 bit data");
+ return EC_IllegalParameter;
+ }
+ result = m_Item->findAndGetUint16Array(dataTag, data, &num16BitEntries);
+ if (result.good())
+ {
+ Uint16 numDescriptor = 0;
+ // get number of entries according to first value of descriptor
+ result = numEntriesForData(dataTag, numDescriptor);
+ if (result.bad())
+ {
+ DCMIOD_ERROR("Could not determine number of 8 bit entries for " << dataTag);
+ return IOD_EC_InvalidColorPalette;
+ }
+ num8BitEntries = numDescriptor;
+ if (num8BitEntries == 0)
+ {
+ num8BitEntries = 256;
+ }
+ // check whether number of entries is consistent with number of 16 bit entries
+ if ( (num8BitEntries != num16BitEntries*2) && (num8BitEntries != num16BitEntries*2 -1) )
+ {
+ DCMIOD_DEBUG("Number of 8 bit entries from descriptor: " << numDescriptor << ", Number of 16 bit entries in data: " << num16BitEntries);
+ DCMIOD_ERROR("Number of 8 bit entries does not match number of 16 bit entries");
+ return IOD_EC_InvalidColorPalette;
+ }
+ Uint8* newData = new Uint8[num8BitEntries];
+ if (num8BitEntries > 1)
+ {
+ for (unsigned long i = 0; i < num16BitEntries - 1; i++)
+ {
+ // extract lower and higher byte of 16 bit entry
+ newData[i * 2] = OFstatic_cast(Uint8, data[i] >> 8);
+ newData[i * 2 + 1] = OFstatic_cast(Uint8, data[i] & 0x00FF);
+ }
+ }
+ if (num8BitEntries % 2)
+ {
+ // if odd number of 16 bit entries, only extract lower byte of last entry
+ newData[num8BitEntries-1] = OFstatic_cast(Uint8, data[num16BitEntries-1] >> 8);
+ }
+ else
+ {
+ newData[num8BitEntries-2] = OFstatic_cast(Uint8, data[num16BitEntries-1] >> 8);
+ newData[num8BitEntries-1] = OFstatic_cast(Uint8, data[num16BitEntries-1] & 0x00FF);
+ }
+ lutData = newData;
+ }
+ return result;
+}
+
+
+OFCondition IODPaletteColorLUTModule::getUint16Data(const DcmTagKey& dataTag, const Uint16*& lutData, unsigned long& numEntries)
+{
+ OFCondition result;
+ const Uint16* data = NULL;
+
+ result = m_Item->findAndGetUint16Array(dataTag, data, &numEntries, OFFalse);
+ if (result.good())
+ {
+ lutData = data;
+ }
+ return result;
+}
+
+OFCondition IODPaletteColorLUTModule::getUint16DataCopy(const DcmTagKey& dataTag, const Uint16*& lutData, unsigned long& numEntries)
+{
+ const Uint16* buffer;
+ OFCondition result = getUint16Data(dataTag, buffer, numEntries);
+ if (result.good())
+ {
+ Uint16* newData = new Uint16[numEntries];
+ // copy data
+ for (unsigned long i = 0; i < numEntries; i++)
+ {
+ newData[i] = buffer[i];
+ }
+ lutData = newData;
+ }
+ return result;
+}
+
+
+OFCondition IODPaletteColorLUTModule::putUint8Data(const DcmTagKey& dataTag, const Uint8* lutData, const unsigned long num8BitEntries)
+{
+ if (numBits() != 8)
+ {
+ DCMIOD_ERROR("Cannot convert 8 bit data to 16 bit data: Descriptor does not indicate 8 bit data");
+ return EC_IllegalParameter;
+ }
+ OFCondition result;
+ unsigned long num16BitEntries = num8BitEntries / 2 + (num8BitEntries % 2);
+ // put 16 bit data together by combining two 8 bit entries into one 16 bit entry
+ Uint16* newData = new Uint16[num16BitEntries];
+ for (unsigned long i = 0; i < num16BitEntries; i++)
+ {
+ if (i != num16BitEntries-1)
+ {
+ newData[i] = OFstatic_cast(Uint16, lutData[i*2] << 8) | lutData[i*2+1];
+ }
+ else
+ {
+ // if odd number of 8 bit entries, only use lower byte of last entry
+ newData[i] = OFstatic_cast(Uint16, lutData[i*2] << 8);
+ }
+ }
+ // Reset last entry (second part of 16 bit word) to 0 if odd number of 8 bit entries
+ if (num8BitEntries % 2)
+ {
+ newData[num16BitEntries-1] &= 0xFF00;
+ }
+ // otherwise also take over last 8 bit entry
+ else
+ {
+ newData[num16BitEntries-1] |= lutData[num8BitEntries-1];
+ }
+ result = m_Item->putAndInsertUint16Array(dataTag, newData, num16BitEntries);
+ delete[] newData;
+ return result;
+}
+
+
+OFCondition IODPaletteColorLUTModule::numEntriesForData(const DcmTagKey& dataTag, Uint16& result)
+{
+ result = 0;
+ OFCondition cond;
+ if (dataTag == DCM_RedPaletteColorLookupTableData)
+ {
+ cond = getRedPaletteColorLookupTableDescriptor(result, 0);
+ }
+ else if (dataTag == DCM_GreenPaletteColorLookupTableData)
+ {
+ cond = getGreenPaletteColorLookupTableDescriptor(result, 0);
+ }
+ else if (dataTag == DCM_BluePaletteColorLookupTableData)
+ {
+ cond = getBluePaletteColorLookupTableDescriptor(result, 0);
+ }
+ else if (dataTag == DCM_SegmentedRedPaletteColorLookupTableData)
+ {
+ cond = getRedPaletteColorLookupTableDescriptor(result, 0);
+ }
+ else if (dataTag == DCM_SegmentedGreenPaletteColorLookupTableData)
+ {
+ cond = getGreenPaletteColorLookupTableDescriptor(result, 0);
+ }
+ else if (dataTag == DCM_SegmentedBluePaletteColorLookupTableData)
+ {
+ cond = getBluePaletteColorLookupTableDescriptor(result, 0);
+ }
+ else
+ {
+ return EC_InvalidTag;
+ }
+ return cond;
+}
tchecks.cc
tcielabutil.cc
tcodes.cc
+ ticcprofile.cc
timagepixel.cc
+ tmacro.cc
+ tpalette.cc
tests.cc
)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(dcmiod_tests dcmiod dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(dcmiod_tests dcmimgle dcmiod dcmdata oflog ofstd)
# This macro parses tests.cc and registers all tests
DCMTK_ADD_TESTS(dcmiod)
../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../include/dcmtk/dcmiod/iodtypes.h ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../include/dcmtk/dcmiod/modcommoninstanceref.h \
../include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
- ../include/dcmtk/dcmiod/ioddef.h ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
../include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h
+ticcprofile.o: ticcprofile.cc \
+ ../../config/include/dcmtk/config/osconfig.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../include/dcmtk/dcmiod/modiccprofile.h \
+ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/modbase.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h
timagepixel.o: timagepixel.cc \
../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmiod/iodimage.h ../include/dcmtk/dcmiod/iodcommn.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
../../dcmdata/include/dcmtk/dcmdata/dcuid.h
+tmacro.o: tmacro.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../include/dcmtk/dcmiod/iodmacro.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
+ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/modbase.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h
+tpalette.o: tpalette.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../include/dcmtk/dcmiod/iodrules.h ../include/dcmtk/dcmiod/iodtypes.h \
+ ../include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../include/dcmtk/dcmiod/modbase.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h
oflogdir = $(top_srcdir)/../oflog
dcmdatadir = $(top_srcdir)/../dcmdata
dcmioddir = $(top_srcdir)/../dcmiod
+dcmimgledir = $(top_srcdir)/../dcmimgle
LOCALINCLUDES = -I$(dcmioddir)/include -I$(dcmdatadir)/include -I$(oflogdir)/include \
-I$(ofstddir)/include
LIBDIRS = -L$(top_srcdir)/libsrc -L$(dcmioddir)/libsrc -L$(dcmdatadir)/libsrc \
- -L$(oflogdir)/libsrc -L$(ofstddir)/libsrc -L$(oficonvdir)/libsrc
-LOCALLIBS = -ldcmiod -ldcmdata -loflog -lofstd -loficonv \
+ -L$(oflogdir)/libsrc -L$(ofstddir)/libsrc -L$(oficonvdir)/libsrc \
+ -L$(dcmimgledir)/libsrc
+LOCALLIBS = -ldcmiod -ldcmimgle -ldcmdata -loflog -lofstd -loficonv \
$(TIFFLIBS) $(PNGLIBS) $(ZLIBLIBS) $(CHARCONVLIBS) $(MATHLIBS)
-test_objs = tests.o tchecks.o tcielabutil.o tcodes.o timagepixel.o
+test_objs = tests.o tchecks.o tcielabutil.o tcodes.o ticcprofile.o \
+ timagepixel.o tmacro.o tpalette.o
+
objs = tests.o $(test_objs)
progs = tests
/*
*
- * Copyright (C) 2024, OFFIS e.V.
+ * Copyright (C) 2024-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* D-26121 Oldenburg, Germany
*
*
- * Module: dcmect
+ * Module: dcmiod
*
* Author: Michael Onken
*
/*
*
- * Copyright (C) 2016-2024, OFFIS e.V.
+ * Copyright (C) 2016-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFTEST_REGISTER(dcmiod_component_check_vm_violated);
OFTEST_REGISTER(dcmiod_component_check_vr_violated);
OFTEST_REGISTER(dcmiod_codes);
+OFTEST_REGISTER(dcmiod_content_identification_macro);
+OFTEST_REGISTER(dcmiod_icc_profile_module);
OFTEST_REGISTER(dcmiod_imagepixel);
OFTEST_REGISTER(dcmiod_tcielabutil);
+OFTEST_REGISTER(dcmiod_palette_color_lut_module);
+OFTEST_REGISTER(dcmiod_palette_color_lut_module_segmented);
+OFTEST_REGISTER(dcmiod_palette_color_lut_module_extra_checks);
OFTEST_MAIN("dcmiod")
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Tests for dcmiod's checks
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/oflog/oflog.h"
+#include "dcmtk/dcmdata/dcdict.h"
+#include "dcmtk/dcmiod/modiccprofile.h"
+#include "dcmtk/ofstd/oftest.h"
+
+
+static const Uint8 ICC_LENGTH = 100;
+static const OFString COLOR_SPACE("SRGB");
+
+static void fillICCProfile(IODICCProfileModule& mod);
+static void checkICCProfile(IODICCProfileModule& mod);
+static void checkReadWriteICCProfile(IODICCProfileModule& mod);
+
+static OFLogger tLog = OFLog::getLogger("dcmtk.test.ticcprofile");
+
+
+/** Make sure dictionary is loaded
+ * @return OFTrue if dictionary is loaded, OFFalse otherwise
+ */
+static OFBool checkDictionary()
+{
+ // Make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
+ return OFFalse;
+ }
+ return OFTrue;
+}
+
+OFTEST(dcmiod_icc_profile_module)
+{
+ OFCHECK(checkDictionary());
+ IODICCProfileModule mod;
+
+ fillICCProfile(mod);
+ checkICCProfile(mod);
+ checkReadWriteICCProfile(mod);
+}
+
+
+static void fillICCProfile(IODICCProfileModule& mod)
+{
+ Uint8* iccProfile = new Uint8[ICC_LENGTH];
+ for (Uint8 i = 0; i < ICC_LENGTH; i++)
+ {
+ iccProfile[i] = i;
+ }
+ OFCHECK(mod.setICCProfile(iccProfile, ICC_LENGTH, OFTrue /* check */).good());
+ OFCHECK(mod.setColorSpace(COLOR_SPACE, OFTrue /* check */).good());
+
+ delete[] iccProfile;
+}
+
+
+static void checkICCProfile(IODICCProfileModule& mod)
+{
+ const Uint8* iccProfile = NULL;
+ Uint32 length = 0;
+ OFCHECK(mod.getICCProfile(iccProfile, length).good());
+ OFCHECK(length == ICC_LENGTH);
+ for (unsigned long i = 0; i < ICC_LENGTH; i++)
+ {
+ OFCHECK(iccProfile[i] == i);
+ }
+ OFString colorSpace;
+ OFCHECK(mod.getColorSpace(colorSpace).good());
+ OFCHECK(colorSpace == COLOR_SPACE);
+ delete [] iccProfile; // clean up, this is a copy
+}
+
+
+static void checkReadWriteICCProfile(IODICCProfileModule& mod)
+{
+ // Write to item and check all values using dcmdata API
+ DcmItem item;
+ OFCHECK(mod.write(item).good());
+ const Uint8* profile = NULL;
+ unsigned long count = 0;;
+ OFCHECK(item.findAndGetUint8Array(DCM_ICCProfile, profile, &count).good());
+ OFCHECK(count == ICC_LENGTH);
+ for (unsigned long i = 0; i < ICC_LENGTH; i++)
+ {
+ OFCHECK(profile[i] == i);
+ }
+ OFString colorSpace;
+ OFCHECK(item.findAndGetOFString(DCM_ColorSpace, colorSpace).good());
+ OFCHECK(colorSpace == COLOR_SPACE);
+
+ // Read from item and check all values from module class
+ IODICCProfileModule mod2;
+ OFCHECK(mod2.read(item).good());
+ checkICCProfile(mod2);
+}
\ No newline at end of file
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Tests for dcmiod macros
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/oftest.h"
+#include "dcmtk/dcmiod/iodmacro.h"
+
+
+OFTEST(dcmiod_content_identification_macro)
+{
+ ContentIdentificationMacro macro;
+ OFCHECK((macro.check(OFTrue /* quiet */).bad()));
+
+ OFCHECK(macro.setContentCreatorName("OC").good());
+ OFCHECK(macro.setContentDescription("Test Description").good());
+ OFCHECK(macro.setContentLabel("TEST_LABEL").good());
+ OFCHECK(macro.setInstanceNumber("42").good());
+
+ OFCHECK(macro.check(OFTrue /* quiet */).good());
+ OFString str;
+
+ // Check all strings
+ OFCHECK(macro.getContentCreatorName(str).good());
+ OFCHECK(str == "OC");
+ OFCHECK(macro.getContentDescription(str).good());
+ OFCHECK(str == "Test Description");
+ OFCHECK(macro.getContentLabel(str).good());
+ OFCHECK(str == "TEST_LABEL");
+ OFCHECK(macro.getInstanceNumber(str).good());
+ OFCHECK(str == "42");
+
+ // Write and re-read
+ DcmItem item;
+ OFCHECK(macro.write(item).good());
+ ContentIdentificationMacro macro2;
+ OFCHECK(macro2.read(item).good());
+ OFCHECK(macro2.check(OFTrue /* quiet */).good());
+
+ // Check strings in macro2
+ OFCHECK(macro2.getContentCreatorName(str).good());
+ OFCHECK(str == "OC");
+ OFCHECK(macro2.getContentDescription(str).good());
+ OFCHECK(str == "Test Description");
+ OFCHECK(macro2.getContentLabel(str).good());
+ OFCHECK(str == "TEST_LABEL");
+ OFCHECK(macro2.getInstanceNumber(str).good());
+ OFCHECK(str == "42");
+}
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmiod
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Tests for dcmiod's checks
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/oflog/oflog.h"
+#include "dcmtk/dcmdata/dcdict.h"
+#include "dcmtk/dcmiod/modpalettecolorlut.h"
+#include "dcmtk/ofstd/oftest.h"
+#include "dcmtk/ofstd/oflimits.h"
+#include "dcmtk/ofstd/ofdiag.h"
+
+
+template<typename T> static T* makePixelData(unsigned long& num_entries);
+template<typename T> static OFBool verifyPixelData(T* dataFound, T* data, const unsigned long& num_entries);
+template<typename T> static void createNonSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data);
+template<typename T> static void checkNonSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data);
+
+template<typename T> static void createSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data);
+template<typename T> static void checkSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data);
+
+
+
+static void clear(IODPaletteColorLUTModule& mod);
+
+static OFLogger tLog = OFLog::getLogger("dcmtk.test.tpalette");
+
+/** Make sure dictionary is loaded
+ * @return OFTrue if dictionary is loaded, OFFalse otherwise
+ */
+static OFBool checkDictionary()
+{
+ // Make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
+ return OFFalse;
+ }
+ return OFTrue;
+}
+
+OFTEST(dcmiod_palette_color_lut_module)
+{
+ OFCHECK(checkDictionary());
+ IODPaletteColorLUTModule mod;
+
+ // 16 Bit data
+ unsigned long num_entries = 65535;
+ Uint8 num_bits = 16;
+ const Uint16* data16bit = makePixelData<Uint16>(num_entries);
+ createNonSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data16bit);
+ checkNonSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data16bit);
+ clear(mod);
+ delete[] data16bit;
+
+ // 16 bit max entries
+ num_entries = 65536;
+ num_bits = 16;
+ const Uint16* data16bitMax = makePixelData<Uint16>(num_entries);
+ createNonSegmentedPaletteModule(mod, num_bits, 0, data16bitMax);
+ checkNonSegmentedPaletteModule(mod, num_bits, 0, data16bitMax);
+ clear(mod);
+ delete[] data16bitMax;
+
+ // 8 bit data
+ num_entries = 255;
+ num_bits = 8;
+ const Uint8* data8bit = makePixelData<Uint8>(num_entries);
+ createNonSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data8bit);
+ checkNonSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data8bit);
+ clear(mod);
+ delete[] data8bit;
+
+ // 8 bit max entries
+ num_entries = 256;
+ num_bits = 8;
+ const Uint8* data8bitMax = makePixelData<Uint8>(num_entries);
+ createNonSegmentedPaletteModule(mod, num_bits, 0, data8bitMax);
+ checkNonSegmentedPaletteModule(mod, num_bits, 0, data8bitMax);
+ clear(mod);
+ delete[] data8bitMax;
+}
+
+OFTEST(dcmiod_palette_color_lut_module_segmented)
+{
+ OFCHECK(checkDictionary());
+ IODPaletteColorLUTModule mod;
+
+ // 16 Bit data
+ unsigned long num_entries = 65535;
+ Uint8 num_bits = 16;
+ const Uint16* data16bit = makePixelData<Uint16>(num_entries);
+ createSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data16bit);
+ checkSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data16bit);
+ clear(mod);
+ delete[] data16bit;
+
+ // 16 bit max entries
+ num_entries = 65536;
+ num_bits = 16;
+ const Uint16* data16bitMax = makePixelData<Uint16>(num_entries);
+ createSegmentedPaletteModule(mod, num_bits, 0, data16bitMax);
+ checkSegmentedPaletteModule(mod, num_bits, 0, data16bitMax);
+ clear(mod);
+ delete[] data16bitMax;
+
+ // 8 bit data
+ num_entries = 255;
+ num_bits = 8;
+ const Uint8* data8bit = makePixelData<Uint8>(num_entries);
+ createSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data8bit);
+ checkSegmentedPaletteModule(mod, num_bits, OFstatic_cast(Uint16, num_entries), data8bit);
+ clear(mod);
+ delete[] data8bit;
+
+ // 8 bit max entries
+ num_entries = 256;
+ num_bits = 8;
+ const Uint8* data8bitMax = makePixelData<Uint8>(num_entries);
+ createSegmentedPaletteModule(mod, num_bits, 0, data8bitMax);
+ checkSegmentedPaletteModule(mod, num_bits, 0, data8bitMax);
+ clear(mod);
+ delete[] data8bitMax;
+}
+
+OFTEST(dcmiod_palette_color_lut_module_extra_checks)
+{
+ // 16 bit data with 8 bit descriptor fails
+ IODPaletteColorLUTModule mod;
+ unsigned long num_entries = 255;
+ const Uint16* data16bit = makePixelData<Uint16>(num_entries);
+ OFCHECK(mod.setRedPaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 8).good());
+ OFCHECK(mod.setGreenPaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 8).good());
+ OFCHECK(mod.setBluePaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 8).good());
+ // Now try to set 16 LUT Data
+ OFCHECK(mod.setRedPaletteColorLookupTableData(data16bit, num_entries).bad());
+ OFCHECK(mod.setGreenPaletteColorLookupTableData(data16bit, num_entries).bad());
+ OFCHECK(mod.setBluePaletteColorLookupTableData(data16bit, num_entries).bad());
+ delete[] data16bit;
+ mod.clearData();
+
+ // 8 bit data with 16 bit descriptor fails
+ num_entries = 65535;
+ Uint8* data8bit = new Uint8[num_entries];
+ memset(data8bit, 0, num_entries * sizeof(Uint8)); // vallues will be not exercised at all
+ OFCHECK(mod.setRedPaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 16).good());
+ OFCHECK(mod.setGreenPaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 16).good());
+ OFCHECK(mod.setBluePaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 16).good());
+ // Now try to set 8 LUT Data
+ OFCHECK(mod.setRedPaletteColorLookupTableData(data8bit, num_entries).bad());
+ OFCHECK(mod.setGreenPaletteColorLookupTableData(data8bit, num_entries).bad());
+ OFCHECK(mod.setBluePaletteColorLookupTableData(data8bit, num_entries).bad());
+ delete[] data8bit;
+
+ // mix of segment and non segment data fails
+ num_entries = 65535;
+ DcmItem item;
+ data16bit = makePixelData<Uint16>(num_entries);
+ OFCHECK(mod.setRedPaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 16).good());
+ OFCHECK(mod.setGreenPaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 16).good());
+ OFCHECK(mod.setBluePaletteColorLookupTableDescriptor(OFstatic_cast(Uint16, num_entries), 0, 16).good());
+ OFCHECK(mod.setSegmentedRedPaletteColorLookupTableData(data16bit, num_entries).good());
+ OFCHECK(mod.setSegmentedGreenPaletteColorLookupTableData(data16bit, num_entries).good());
+ OFCHECK(mod.setSegmentedBluePaletteColorLookupTableData(data16bit, num_entries).good());
+ // this does not make sense:
+ OFCHECK(mod.setRedPaletteColorLookupTableData(data16bit, num_entries).good());
+ OFCHECK(mod.setGreenPaletteColorLookupTableData(data16bit, num_entries).good());
+ OFCHECK(mod.setBluePaletteColorLookupTableData(data16bit, num_entries).good());
+ OFCHECK(mod.write(item).bad());
+ delete[] data16bit;
+
+}
+
+
+template<typename T>
+static T* makePixelData(unsigned long& num_entries)
+{
+#include DCMTK_DIAGNOSTIC_PUSH
+#include DCMTK_DIAGNOSTIC_IGNORE_VISUAL_STUDIO_CONSTANT_EXPRESSION_WARNING
+ if (!OFnumeric_limits<T>::is_signed && (OFnumeric_limits<T>::max() < num_entries - 1))
+ {
+ OFCHECK_MSG(OFFalse, "Internal error, cannot create pixel data for given type T, too many entries.");
+ }
+ else if (OFnumeric_limits<T>::is_signed && (OFstatic_cast(unsigned long, OFnumeric_limits<T>::max()) / 2 > num_entries - 1))
+ {
+ OFCHECK_MSG(OFFalse, "Internal error, cannot create pixel data for given type T, too many entries.");
+ }
+#include DCMTK_DIAGNOSTIC_POP
+
+ T* data = new T[num_entries];
+ for (unsigned long i = 0; i < num_entries; i++)
+ {
+ // Casts are safe since we check the limits above,
+ // and this way the compiler does not complain about narrowing conversions
+ if (OFnumeric_limits<T>::is_signed)
+ data[i] = OFstatic_cast(T, i - num_entries / 2);
+ else
+ data[i] = OFstatic_cast(T, i);
+ }
+ return data;
+}
+
+template<typename T>
+static OFBool verifyPixelData(T* dataFound, T* data, const unsigned long& num_entries)
+{
+ if (!data || !dataFound)
+ {
+ return OFFalse;
+ }
+
+ for (unsigned int i = 0; i < num_entries; i++)
+ {
+ if (dataFound[i] != data[i])
+ {
+ OFLOG_DEBUG(tLog, "Pixel data at index " << OFstatic_cast(Uint16, i) << " is " << OFstatic_cast(Uint16, dataFound[i]) << " but should be " << OFstatic_cast(Uint16, data[i]));
+ return OFFalse;
+ }
+ }
+ return OFTrue;
+}
+
+static void clear(IODPaletteColorLUTModule& mod)
+{
+ mod.clearData();
+ OFCHECK(mod.numBits() == 0);
+}
+
+
+template<typename T>
+static void createNonSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data)
+{
+ OFCHECK_MSG(mod.setRedPaletteColorLookupTableDescriptor(numEntries, 0, bits).good(), "Cannot set Red Palette Color Lookup Table Descriptor");
+ OFCHECK_MSG(mod.setGreenPaletteColorLookupTableDescriptor(numEntries, 0, bits).good(), "Cannot set Green Palette Color Lookup Table Descriptor");
+ OFCHECK_MSG(mod.setBluePaletteColorLookupTableDescriptor(numEntries, 0, bits).good(), "Cannot set Blue Palette Color Lookup Table Descriptor");
+ OFCHECK_MSG(mod.setPaletteColorLookupTableUID("1.2.3.4").good(), "Cannot set Palette Color Lookup Table UID (1.2.3.4)");
+
+ OFCHECK_MSG(mod.setRedPaletteColorLookupTableData(data, numEntries).good(), "Cannot set Red Palette Color Lookup Table Data");
+ OFCHECK_MSG(mod.setGreenPaletteColorLookupTableData(data, numEntries).good(), "Cannot set Green Palette Color Lookup Table Data");
+ OFCHECK_MSG(mod.setBluePaletteColorLookupTableData(data, numEntries).good(), "Cannot set Blue Palette Color Lookup Table Data");
+}
+
+template<typename T>
+static void createSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data)
+{
+ OFCHECK_MSG(mod.setRedPaletteColorLookupTableDescriptor(numEntries, 0, bits).good(), "Cannot set Red Palette Color Lookup Table Descriptor");
+ OFCHECK_MSG(mod.setGreenPaletteColorLookupTableDescriptor(numEntries, 0, bits).good(), "Cannot set Green Palette Color Lookup Table Descriptor");
+ OFCHECK_MSG(mod.setBluePaletteColorLookupTableDescriptor(numEntries, 0, bits).good(), "Cannot set Blue Palette Color Lookup Table Descriptor");
+ OFCHECK_MSG(mod.setPaletteColorLookupTableUID("1.2.3.4").good(), "Cannot set Palette Color Lookup Table UID (1.2.3.4)");
+
+ OFCHECK_MSG(mod.setSegmentedRedPaletteColorLookupTableData(data, numEntries).good(), "Cannot set Segmented Red Palette Color Lookup Table Data");
+ OFCHECK_MSG(mod.setSegmentedGreenPaletteColorLookupTableData(data, numEntries).good(), "Cannot set Segmented Green Palette Color Lookup Table Data");
+ OFCHECK_MSG(mod.setSegmentedBluePaletteColorLookupTableData(data, numEntries).good(), "Cannot set Segmented Blue Palette Color Lookup Table Data");
+}
+
+
+template<typename T>
+static void checkNonSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data)
+{
+ DcmItem item;
+ OFString uid;
+ Uint16 d1,d2,d3;
+ d1 = d2 = d3 = 1; // not used in test data
+ OFCHECK_MSG(mod.write(item).good(), "Cannot write Palette Color Lookup Table Module to DcmItem");
+ OFCHECK_MSG(mod.numBits() == bits, "getBits() returns wrong value for Palette Color Lookup Table Module");
+ OFCHECK_MSG(mod.getPaletteColorLookupTableUID(uid).good(), "Cannot get Palette Color Lookup Table UID");
+ OFCHECK(mod.getRedPaletteColorLookupTableDescriptor(d1, 0).good());
+ OFCHECK(mod.getRedPaletteColorLookupTableDescriptor(d2, 1).good());
+ OFCHECK(mod.getRedPaletteColorLookupTableDescriptor(d3, 2).good());
+ OFCHECK(d1 == numEntries);
+ OFCHECK(d2 == 0);
+ OFCHECK(d3 == bits);
+ d1 = d2 = d3 = 1; // not used in test data
+ OFCHECK(mod.getGreenPaletteColorLookupTableDescriptor(d1, 0).good());
+ OFCHECK(mod.getGreenPaletteColorLookupTableDescriptor(d2, 1).good());
+ OFCHECK(mod.getGreenPaletteColorLookupTableDescriptor(d3, 2).good());
+ OFCHECK(d1 == numEntries);
+ OFCHECK(d2 == 0);
+ OFCHECK(d3 == bits);
+ d1 = d2 = d3 = 1; // not used in test data
+ OFCHECK(mod.getBluePaletteColorLookupTableDescriptor(d1, 0).good());
+ OFCHECK(mod.getBluePaletteColorLookupTableDescriptor(d2, 1).good());
+ OFCHECK(mod.getBluePaletteColorLookupTableDescriptor(d3, 2).good());
+ OFCHECK(d1 == numEntries);
+ OFCHECK(d2 == 0);
+ OFCHECK(d3 == bits);
+
+ OFCHECK(uid == "1.2.3.4");
+ // 16 bit data
+ if (bits == 16)
+ {
+ unsigned long entriesFound = 0;
+ const Uint16 *dataFound16 = NULL;
+ OFCHECK(mod.getRedPaletteColorLookupTableData(dataFound16, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 65536) : numEntries));
+ OFCHECK(verifyPixelData(dataFound16, (const Uint16*)data, numEntries));
+ delete[] dataFound16; dataFound16 = NULL;
+ OFCHECK(mod.getGreenPaletteColorLookupTableData(dataFound16, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 65536) : numEntries));
+ OFCHECK(verifyPixelData(dataFound16, (const Uint16*)data, numEntries));
+ delete[] dataFound16; dataFound16 = NULL;
+ OFCHECK(mod.getBluePaletteColorLookupTableData(dataFound16, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 65536) : numEntries));
+ OFCHECK(verifyPixelData(dataFound16, (const Uint16*)data, numEntries));
+ delete[] dataFound16;
+ }
+ // 8 bit data
+ else if (bits == 8)
+ {
+ unsigned long entriesFound = 0;
+ const Uint8 *dataFound8 = NULL;
+ OFCHECK(mod.getRedPaletteColorLookupTableData(dataFound8, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 256) : numEntries));
+ OFCHECK(verifyPixelData(dataFound8, (const Uint8*)data, numEntries));
+ delete[] dataFound8; dataFound8 = NULL;
+ OFCHECK(mod.getGreenPaletteColorLookupTableData(dataFound8, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 256) : numEntries));
+ OFCHECK(verifyPixelData(dataFound8, (const Uint8*)data, numEntries));
+ delete[] dataFound8; dataFound8 = NULL;
+ OFCHECK(mod.getBluePaletteColorLookupTableData(dataFound8, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 256) : numEntries));
+ OFCHECK(verifyPixelData(dataFound8, (const Uint8*)data, numEntries));
+ delete[] dataFound8;
+ }
+ else
+ {
+ OFCHECK_FAIL("Unsupported bit depth");
+ }
+}
+
+
+template<typename T>
+static void checkSegmentedPaletteModule(IODPaletteColorLUTModule& mod, Uint8 bits, const Uint16 numEntries, const T*& data)
+{
+ DcmItem item;
+ OFString uid;
+ unsigned long entriesFound = 0;
+ Uint16 d1,d2,d3;
+ d1 = d2 = d3 = 1; // not used in test data
+ OFCHECK_MSG(mod.write(item).good(), "Cannot write (segmented) Palette Color Lookup Table Module to DcmItem");
+ OFCHECK_MSG(mod.numBits() == bits, "getBits() returns wrong value for Palette Color Lookup Table Module");
+ OFCHECK_MSG(mod.getPaletteColorLookupTableUID(uid).good(), "Cannot get Palette Color Lookup Table UID");
+ OFCHECK(mod.getRedPaletteColorLookupTableDescriptor(d1, 0).good());
+ OFCHECK(mod.getRedPaletteColorLookupTableDescriptor(d2, 1).good());
+ OFCHECK(mod.getRedPaletteColorLookupTableDescriptor(d3, 2).good());
+ OFCHECK(d1 == numEntries);
+ OFCHECK(d2 == 0);
+ OFCHECK(d3 == bits);
+ d1 = d2 = d3 = 1; // not used in test data
+ OFCHECK(mod.getGreenPaletteColorLookupTableDescriptor(d1, 0).good());
+ OFCHECK(mod.getGreenPaletteColorLookupTableDescriptor(d2, 1).good());
+ OFCHECK(mod.getGreenPaletteColorLookupTableDescriptor(d3, 2).good());
+ OFCHECK(d1 == numEntries);
+ OFCHECK(d2 == 0);
+ OFCHECK(d3 == bits);
+ d1 = d2 = d3 = 1; // not used in test data
+ OFCHECK(mod.getBluePaletteColorLookupTableDescriptor(d1, 0).good());
+ OFCHECK(mod.getBluePaletteColorLookupTableDescriptor(d2, 1).good());
+ OFCHECK(mod.getBluePaletteColorLookupTableDescriptor(d3, 2).good());
+ OFCHECK(d1 == numEntries);
+ OFCHECK(d2 == 0);
+ OFCHECK(d3 == bits);
+
+ OFCHECK(uid == "1.2.3.4");
+ // 16 bit data
+ if (bits == 16)
+ {
+ const Uint16 *dataFound16 = NULL;
+ OFCHECK(mod.getSegmentedRedPaletteColorLookupTableData(dataFound16, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 65536) : numEntries));
+ OFCHECK(verifyPixelData(dataFound16, (const Uint16*)data, numEntries));
+ delete[] dataFound16; dataFound16 = NULL;
+ OFCHECK(mod.getSegmentedGreenPaletteColorLookupTableData(dataFound16, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 65536) : numEntries));
+ OFCHECK(verifyPixelData(dataFound16, (const Uint16*)data, numEntries));
+ delete[] dataFound16; dataFound16 = NULL;
+ OFCHECK(mod.getSegmentedBluePaletteColorLookupTableData(dataFound16, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 65536) : numEntries));
+ OFCHECK(verifyPixelData(dataFound16, (const Uint16*)data, numEntries));
+ delete[] dataFound16;
+ }
+ // 8 bit data
+ else if (bits == 8)
+ {
+ const Uint8 *dataFound8 = NULL;
+ OFCHECK(mod.getSegmentedRedPaletteColorLookupTableData(dataFound8, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 256) : numEntries));
+ OFCHECK(verifyPixelData(dataFound8, (const Uint8*)data, numEntries));
+ delete[] dataFound8; dataFound8 = NULL;
+ OFCHECK(mod.getSegmentedGreenPaletteColorLookupTableData(dataFound8, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 256) : numEntries));
+ OFCHECK(verifyPixelData(dataFound8, (const Uint8*)data, numEntries));
+ delete[] dataFound8; dataFound8 = NULL;
+ OFCHECK(mod.getSegmentedBluePaletteColorLookupTableData(dataFound8, entriesFound).good());
+ OFCHECK(entriesFound == ((numEntries == 0) ? OFstatic_cast(unsigned long, 256) : numEntries));
+ OFCHECK(verifyPixelData(dataFound8, (const Uint8*)data, numEntries));
+ delete[] dataFound8;
+ }
+ else
+ {
+ OFCHECK_FAIL("Unsupported bit depth");
+ }
+}
\ No newline at end of file
/*
*
- * Copyright (C) 2001-2022, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFBool opt_predictor6WorkaroundEnable = OFFalse;
OFBool opt_cornellWorkaroundEnable = OFFalse;
OFBool opt_forceSingleFragmentPerFrame = OFFalse;
+ OFBool opt_preserveBitsStored = OFFalse;
OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Decode JPEG-compressed DICOM file", rcsid);
OFCommandLine cmd;
cmd.addOption("--color-by-pixel", "+px", "always store color-by-pixel");
cmd.addOption("--color-by-plane", "+pl", "always store color-by-plane");
+ cmd.addSubGroup("bits stored:");
+ cmd.addOption("--bits-stored-fix", "+bs", "correct inconsistent bits stored value (default)");
+ cmd.addOption("--bits-stored-keep", "-bs", "preserve inconsistent bits stored value");
+
cmd.addSubGroup("SOP Instance UID:");
cmd.addOption("--uid-default", "+ud", "keep same SOP Instance UID (default)");
cmd.addOption("--uid-always", "+ua", "always assign new UID");
if (cmd.findOption("--color-by-plane")) opt_planarconfig = EPC_colorByPlane;
cmd.endOptionBlock();
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--bits-stored-fix")) opt_preserveBitsStored = OFFalse;
+ if (cmd.findOption("--bits-stored-keep")) opt_preserveBitsStored = OFTrue;
+ cmd.beginOptionBlock();
+
cmd.beginOptionBlock();
if (cmd.findOption("--conv-photometric")) opt_decompCSconversion = EDC_photometricInterpretation;
if (cmd.findOption("--conv-lossy")) opt_decompCSconversion = EDC_lossyOnly;
opt_planarconfig,
opt_predictor6WorkaroundEnable,
opt_cornellWorkaroundEnable,
- opt_forceSingleFragmentPerFrame);
+ opt_forceSingleFragmentPerFrame,
+ opt_preserveBitsStored);
/* make sure data dictionary is loaded */
if (!dcmDataDict.isDictionaryLoaded())
\section dcmcjpeg_copyright COPYRIGHT
-Copyright (C) 2001-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2001-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
# If the compressed image is a color image, store in color-by-plane
# planar configuration.
+bits stored:
+
+ +bs --bits-stored-fix
+ correct inconsistent bits stored value (default)
+
+ # If the value of BitsStored in the compressed bitstream is smaller
+ # than the value in the DICOM dataset, update the value in the dataset.
+
+ -bs --bits-stored-keep
+ preserve inconsistent bits stored value
+
+ # Keep the value of BitsStored even if inconsistent with the
+ # compressed bitstream. This may help in correctly decoding some
+ # defective images.
+
SOP Instance UID:
+ud --uid-default
\section dcmdjpeg_copyright COPYRIGHT
-Copyright (C) 2001-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2001-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmj2pnm_copyright COPYRIGHT
-Copyright (C) 2001-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2001-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmmkdir_copyright COPYRIGHT
-Copyright (C) 2001-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2001-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 2001-2020, OFFIS e.V.
+ * Copyright (C) 2001-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_TransferSyntax oldRepType,
const E_TransferSyntax newRepType) const;
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded with this codec.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
/** determine color model of the decompressed image
* @param fromParam representation parameter of current compressed
* representation, may be NULL
/*
*
- * Copyright (C) 2001-2020, OFFIS e.V.
+ * Copyright (C) 2001-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_TransferSyntax oldRepType,
const E_TransferSyntax newRepType) const;
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded with this codec.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
/** determine color model of the decompressed image
* @param fromParam representation parameter of current compressed
* representation, may be NULL
/*
*
- * Copyright (C) 1997-2018, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* @param pAcrNemaCompatibility accept old ACR-NEMA images without photometric interpretation
* (only "pseudo" lossless encoder)
* @param pTrueLosslessMode Enables true lossless compression (replaces old "pseudo lossless" encoder)
+ * @param setPreserveBitsStored preserve BitsStored when decompressing even if inconsistent with J2K bitstream
*/
DJCodecParameter(
E_CompressionColorSpaceConversion pCompressionCSConversion,
OFBool pUseModalityRescale = OFFalse,
OFBool pAcceptWrongPaletteTags = OFFalse,
OFBool pAcrNemaCompatibility = OFFalse,
- OFBool pTrueLosslessMode = OFTrue);
+ OFBool pTrueLosslessMode = OFTrue,
+ OFBool setPreserveBitsStored = OFFalse);
/// copy constructor
DJCodecParameter(const DJCodecParameter& arg);
return forceSingleFragmentPerFrame;
}
+ /** returns flag indicating whether to preserve the
+ * value of BitsStored even if inconsistent with the
+ * compressed bitstream.
+ */
+ OFBool getPreserveBitsStored() const
+ {
+ return setPreserveBitsStored_;
+ }
+
private:
/// private undefined copy assignment operator
*/
OFBool forceSingleFragmentPerFrame;
+ /// flag indicating whether BitsStored should be preserved when decompressing even if inconsistent with the J2K bitstream
+ OFBool setPreserveBitsStored_;
+
};
/*
*
- * Copyright (C) 1997-2018, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* Huffman table overflow
* @param pForceSingleFragmentPerFrame while decompressing a multiframe image,
* assume one fragment per frame even if the JPEG data for some frame is incomplete
+ * @param setPreserveBitsStored preserve BitsStored when decompressing even if inconsistent with J2K bitstream
*/
static void registerCodecs(
E_DecompressionColorSpaceConversion pDecompressionCSConversion = EDC_photometricInterpretation,
E_PlanarConfiguration pPlanarConfiguration = EPC_default,
OFBool predictor6WorkaroundEnable = OFFalse,
OFBool cornellWorkaroundEnable = OFFalse,
- OFBool pForceSingleFragmentPerFrame = OFFalse);
+ OFBool pForceSingleFragmentPerFrame = OFFalse,
+ OFBool setPreserveBitsStored = OFFalse);
/** deregisters decoders.
* Attention: Must not be called while other threads might still use
#include "dcmtk/config/osconfig.h"
-/* We assume ANSI C and don't support DOS,
- * so the following settings need not be tested
+/* We assume ANSI C and don't support DOS,
+ * so the following settings need not be tested
*/
-#define HAVE_PROTOTYPES
-#define HAVE_UNSIGNED_CHAR
-#define HAVE_UNSIGNED_SHORT
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
#undef NEED_FAR_POINTERS
#undef INCOMPLETE_TYPES_BROKEN
#define CHAR_IS_UNSIGNED
#endif
-#ifdef HAVE_SYS_TYPES_H
#define NEED_SYS_TYPES_H
-#endif
/* must always be defined for our implementation */
#define NEED_SHORT_EXTERNAL_NAMES
}
/* Format the message into the passed buffer */
-#ifdef HAVE_VSNPRINTF
if (isstring)
snprintf(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s);
else
err->msg_parm.i[2], err->msg_parm.i[3],
err->msg_parm.i[4], err->msg_parm.i[5],
err->msg_parm.i[6], err->msg_parm.i[7]);
-#else /* HAVE_VSNPRINTF */
- if (isstring)
- sprintf(buffer, msgtext, err->msg_parm.s);
- else
- sprintf(buffer, msgtext,
- err->msg_parm.i[0], err->msg_parm.i[1],
- err->msg_parm.i[2], err->msg_parm.i[3],
- err->msg_parm.i[4], err->msg_parm.i[5],
- err->msg_parm.i[6], err->msg_parm.i[7]);
-#endif /* HAVE_VSNPRINTF */
}
#include "dcmtk/config/osconfig.h"
-/* We assume ANSI C and don't support DOS,
- * so the following settings need not be tested
+/* We assume ANSI C and don't support DOS,
+ * so the following settings need not be tested
*/
-#define HAVE_PROTOTYPES
-#define HAVE_UNSIGNED_CHAR
-#define HAVE_UNSIGNED_SHORT
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
#undef NEED_FAR_POINTERS
#undef INCOMPLETE_TYPES_BROKEN
#define CHAR_IS_UNSIGNED
#endif
-#ifdef HAVE_SYS_TYPES_H
#define NEED_SYS_TYPES_H
-#endif
/* must always be defined for our implementation */
#define NEED_SHORT_EXTERNAL_NAMES
}
/* Format the message into the passed buffer */
-#ifdef HAVE_VSNPRINTF
if (isstring)
snprintf(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s);
else
err->msg_parm.i[2], err->msg_parm.i[3],
err->msg_parm.i[4], err->msg_parm.i[5],
err->msg_parm.i[6], err->msg_parm.i[7]);
-#else /* HAVE_VSNPRINTF */
- if (isstring)
- sprintf(buffer, msgtext, err->msg_parm.s);
- else
- sprintf(buffer, msgtext,
- err->msg_parm.i[0], err->msg_parm.i[1],
- err->msg_parm.i[2], err->msg_parm.i[3],
- err->msg_parm.i[4], err->msg_parm.i[5],
- err->msg_parm.i[6], err->msg_parm.i[7]);
-#endif /* HAVE_VSNPRINTF */
}
#include "dcmtk/config/osconfig.h"
-/* We assume ANSI C and don't support DOS,
- * so the following settings need not be tested
+/* We assume ANSI C and don't support DOS,
+ * so the following settings need not be tested
*/
-#define HAVE_PROTOTYPES
-#define HAVE_UNSIGNED_CHAR
-#define HAVE_UNSIGNED_SHORT
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
#undef NEED_FAR_POINTERS
#undef INCOMPLETE_TYPES_BROKEN
#define CHAR_IS_UNSIGNED
#endif
-#ifdef HAVE_SYS_TYPES_H
#define NEED_SYS_TYPES_H
-#endif
/* must always be defined for our implementation */
#define NEED_SHORT_EXTERNAL_NAMES
}
/* Format the message into the passed buffer */
-#ifdef HAVE_VSNPRINTF
if (isstring)
snprintf(buffer, JMSG_LENGTH_MAX, msgtext, err->msg_parm.s);
else
err->msg_parm.i[2], err->msg_parm.i[3],
err->msg_parm.i[4], err->msg_parm.i[5],
err->msg_parm.i[6], err->msg_parm.i[7]);
-#else /* HAVE_VSNPRINTF */
- if (isstring)
- sprintf(buffer, msgtext, err->msg_parm.s);
- else
- sprintf(buffer, msgtext,
- err->msg_parm.i[0], err->msg_parm.i[1],
- err->msg_parm.i[2], err->msg_parm.i[3],
- err->msg_parm.i[4], err->msg_parm.i[5],
- err->msg_parm.i[6], err->msg_parm.i[7]);
-#endif /* HAVE_VSNPRINTF */
}
../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \
/*
*
- * Copyright (C) 2001-2024, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+Uint16 DJCodecDecoder::decodedBitsAllocated(
+ Uint16 /* bitsAllocated */,
+ Uint16 bitsStored) const
+{
+ // this codec does not support images with less than 2 bits per sample
+ if (bitsStored < 2) return 0;
+
+ // for images with 2..8 bits per sample, BitsAllocated will be 8
+ if (bitsStored <= 8) return 8;
+
+ // for images with 9..16 bits per sample, BitsAllocated will be 16
+ if (bitsStored <= 16) return 16;
+
+ // this codec does not support images with more than 16 bits per sample
+ return 0;
+}
+
+
OFCondition DJCodecDecoder::decode(
const DcmRepresentationParameter * fromRepParam,
DcmPixelSequence * pixSeq,
}
// Bits Stored cannot be larger than precision
- if ((result.good()) && (imageBitsStored > precision))
+ if ((result.good()) && (imageBitsStored > precision) && (! djcp->getPreserveBitsStored()))
{
result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_BitsStored, precision);
}
// High Bit cannot be larger than precision - 1
- if ((result.good()) && (imageHighBit >= precision))
+ if ((result.good()) && (imageHighBit >= precision) && (! djcp->getPreserveBitsStored()))
{
result = OFreinterpret_cast(DcmItem*, dataset)->putAndInsertUint16(DCM_HighBit, OFstatic_cast(Uint16, precision-1));
}
// decompression is complete, finally adjust byte order if necessary
if (jpeg->bytesPerSample() == 1) // we're writing bytes into words
{
+ if ((gLocalByteOrder == EBO_BigEndian) && (frameSize & 1))
+ {
+ DCMJPEG_WARN("Size of frame buffer is odd, cannot correct byte order for last pixel value");
+ }
+
result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, OFreinterpret_cast(Uint16*, buffer), OFstatic_cast(Uint32, frameSize), sizeof(Uint16));
}
}
}
+Uint16 DJCodecEncoder::decodedBitsAllocated(
+ Uint16 /* bitsAllocated */,
+ Uint16 /* bitsStored */) const
+{
+ return 0;
+}
+
+
OFCondition DJCodecEncoder::decode(
const DcmRepresentationParameter * /* fromRepParam */,
DcmPixelSequence * /* pixSeq */,
/*
*
- * Copyright (C) 1997-2018, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFBool pUseModalityRescale,
OFBool pAcceptWrongPaletteTags,
OFBool pAcrNemaCompatibility,
- OFBool pTrueLosslessMode)
+ OFBool pTrueLosslessMode,
+ OFBool setPreserveBitsStored)
: DcmCodecParameter()
, compressionCSConversion(pCompressionCSConversion)
, decompressionCSConversion(pDecompressionCSConversion)
, predictor6WorkaroundEnabled_(predictor6WorkaroundEnable)
, cornellWorkaroundEnabled_(cornellWorkaroundEnable)
, forceSingleFragmentPerFrame(pForceSingleFragmentPerFrame)
+, setPreserveBitsStored_(setPreserveBitsStored)
{
}
, predictor6WorkaroundEnabled_(arg.predictor6WorkaroundEnabled_)
, cornellWorkaroundEnabled_(arg.cornellWorkaroundEnabled_)
, forceSingleFragmentPerFrame(arg.forceSingleFragmentPerFrame)
+, setPreserveBitsStored_(arg.setPreserveBitsStored_)
{
}
/*
*
- * Copyright (C) 1997-2018, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
E_PlanarConfiguration pPlanarConfiguration,
OFBool predictor6WorkaroundEnable,
OFBool cornellWorkaroundEnable,
- OFBool pForceSingleFragmentPerFrame)
+ OFBool pForceSingleFragmentPerFrame,
+ OFBool setPreserveBitsStored)
{
if (! registered)
{
pPlanarConfiguration,
predictor6WorkaroundEnable,
cornellWorkaroundEnable,
- pForceSingleFragmentPerFrame);
+ pForceSingleFragmentPerFrame,
+ OFFalse, 0, 0, 0, OFTrue,
+ ESS_444, OFFalse, OFFalse,
+ 0, 0, 0.0, 0.0, 0, 0, 0, 0,
+ OFTrue, OFFalse, OFFalse, OFFalse, OFTrue,
+ setPreserveBitsStored);
if (cp)
{
# make sure executables are linked to the corresponding libraries
foreach(PROGRAM dcmcjpls dcmdjpls dcml2pnm)
- DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmjpls dcmtkcharls dcmimage dcmimgle dcmdata oflog ofstd ofstd)
+ DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmjpls dcmtkcharls dcmimage)
endforeach()
\section dcmcjpls_copyright COPYRIGHT
-Copyright (C) 2009-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2009-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmdjpls_copyright COPYRIGHT
-Copyright (C) 2009-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2009-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcml2pnm_copyright COPYRIGHT
-Copyright (C) 2001-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2001-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 2007-2020, OFFIS e.V.
+ * Copyright (C) 2007-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_TransferSyntax oldRepType,
const E_TransferSyntax newRepType) const;
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded with this codec.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
/** determine color model of the decompressed image
* @param fromParam representation parameter of current compressed
* representation, may be NULL
Uint16 imageSamplesPerPixel,
Uint16 bytesPerSample);
+ /** decompresses a single frame from the given pixel sequence and
+ * stores the result in the given buffer, without adjusting byte order
+ * @param fromPixSeq compressed pixel sequence
+ * @param cp codec parameters for this codec
+ * @param dataset pointer to dataset in which pixel data element is contained
+ * @param frameNo number of frame, starting with 0 for the first frame
+ * @param startFragment index of the compressed fragment that contains
+ * all or the first part of the compressed bitstream for the given frameNo.
+ * Upon successful return this parameter is updated to contain the index
+ * of the first compressed fragment of the next frame.
+ * When unknown, zero should be passed. In this case the decompression
+ * algorithm will try to determine the index by itself, which will always
+ * work if frames are decompressed in increasing order from first to last,
+ * but may fail if frames are decompressed in random order, multiple fragments
+ * per frame and multiple frames are present in the dataset, and the offset
+ * table is empty.
+ * @param buffer pointer to buffer where frame is to be stored
+ * @param bufSize size of buffer in bytes
+ * @param imageFrames number of frames in this image
+ * @param imageColumns number of columns for each frame
+ * @param imageRows number of rows for each frame
+ * @param imageSamplesPerPixel number of samples per pixel
+ * @param bytesPerSample number of bytes per sample
+ * @return EC_Normal if successful, an error code otherwise.
+ */
+ static OFCondition decodeFrameNoSwap(
+ DcmPixelSequence * fromPixSeq,
+ const DJLSCodecParameter *cp,
+ DcmItem *dataset,
+ Uint32 frameNo,
+ Uint32& startFragment,
+ void *buffer,
+ Uint32 bufSize,
+ Sint32 imageFrames,
+ Uint16 imageColumns,
+ Uint16 imageRows,
+ Uint16 imageSamplesPerPixel,
+ Uint16 bytesPerSample);
+
/** determines if a given image requires color-by-plane planar configuration
* depending on SOP Class UID (DICOM IOD) and photometric interpretation.
* All SOP classes defined in the 2003 edition of the DICOM standard or earlier
/*
*
- * Copyright (C) 2007-2022, OFFIS e.V.
+ * Copyright (C) 2007-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
const E_TransferSyntax oldRepType,
const E_TransferSyntax newRepType) const;
+ /** determines the effective value of BitsAllocated that a dataset will have
+ * after decompression of an image with the given values for bitsAllocated
+ * and bitsStored. This may differ from the bitsAllocated parameter for example
+ * if that value is not a multiple of 8. Returns zero if an image with the
+ * given parameters cannot be decoded with this codec.
+ * @param bitsAllocated current value of Bits Allocated
+ * @param bitsStored current value of Bits Stored
+ * @return value of BitsAllocated after decompression, 0 if no decompression possible
+ */
+ virtual Uint16 decodedBitsAllocated(
+ Uint16 bitsAllocated,
+ Uint16 bitsStored) const;
+
/** determine color model of the decompressed image
* @param fromParam representation parameter of current compressed
* representation, may be NULL
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
#ifndef CHARLS_ENCODERSTRATEGY
#define CHARLS_ENCODERSTRATEGY
bitpos(0),
_isFFWritten(false),
_bytesWritten(0)
-
+
{
}
- virtual ~EncoderStrategy()
+ virtual ~EncoderStrategy()
{
}
LONG PeekByte();
-
+
void OnLineBegin(LONG cpixel, void* ptypeBuffer, LONG pixelStride)
{
_processLine->NewLineRequested(ptypeBuffer, cpixel, pixelStride);
void OnLineEnd(LONG /*cpixel*/, void* /*ptypeBuffer*/, LONG /*pixelStride*/) { }
virtual void SetPresets(const JlsCustomParameters& presets) = 0;
-
+
virtual size_t EncodeScan(const void* rawData, BYTE **ptr, size_t *size, size_t offset, bool compare) = 0;
protected:
valcurrent |= value >> -bitpos;
Flush();
-
+
// A second flush may be required if extra marker-detect bits were needed and not all bits could be written.
if (bitpos < 0)
{
AppendToBitStream(0, (bitpos - 1) % 8);
else
AppendToBitStream(0, bitpos % 8);
-
+
Flush();
ASSERT(bitpos == 0x20);
}
{
write(BYTE(valcurrent >> 24));
_isFFWritten = (*_position)[_current_offset - 1] == 0xFF;
- valcurrent = valcurrent << 8;
+ valcurrent = valcurrent << 8;
bitpos += 8;
}
}
-
+
}
- size_t GetLength()
- {
- return _bytesWritten - (bitpos -32)/8;
+ size_t GetLength()
+ {
+ return _bytesWritten - (bitpos -32)/8;
}
inlinehint void AppendOnesToBitStream(LONG length)
{
- AppendToBitStream((1 << length) - 1, length);
+ AppendToBitStream((1 << length) - 1, length);
}
- OFunique_ptr<DecoderStrategy> _qdecoder;
+ OFunique_ptr<DecoderStrategy> _qdecoder;
protected:
JlsParameters _info;
static BYTE *re_alloc(BYTE *old_ptr, size_t *old_size)
{
size_t new_size = *old_size * 2;
-#ifdef HAVE_STD__NOTHROW
BYTE *new_ptr = new(std::nothrow) BYTE[new_size];
-#else
- BYTE *new_ptr = new BYTE[new_size];
-#endif
if (new_ptr == NULL) {
throw alloc_fail();
}
unsigned int valcurrent;
LONG bitpos;
-
+
// encoding
BYTE **_position;
size_t *_size;
};
-// For some weird reason MSVC6 doesn't like these templates.
// xlC (compiler on AIX) tries to instantiate Triple<Triple<char> > which
// causes compiler errors and is wrong (other compilers don't instantiate it).
-#if (defined(_MSC_VER) && _MSC_VER <= 1200) || defined(__xlC__)
-# define DISABLE_SPECIALIZATIONS
+#ifdef __xlC__
+#define DISABLE_SPECIALIZATIONS
#else
template <class SAMPLE, LONG bpp>
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
#ifndef CHARLS_SCAN
#define CHARLS_SCAN
#include "lokuptbl.h"
-// This file contains the code for handling a "scan". Usually an image is encoded as a single scan.
+// This file contains the code for handling a "scan". Usually an image is encoded as a single scan.
#include DCMTK_DIAGNOSTIC_IGNORE_CONST_EXPRESSION_WARNING
extern OFVector<signed char> rgquant12Ll;
extern OFVector<signed char> rgquant16Ll;
//
-// Apply
+// Apply
//
inlinehint LONG ApplySign(LONG i, LONG sign)
-{ return (sign ^ i) - sign; }
+{ return (sign ^ i) - sign; }
inlinehint LONG GetPredictedValue(LONG Ra, LONG Rb, LONG Rc)
{
- // sign trick reduces the number of if statements (branches)
+ // sign trick reduces the number of if statements (branches)
LONG sgn = BitWiseSign(Rb - Ra);
- // is Ra between Rc and Rb?
+ // is Ra between Rc and Rb?
if ((sgn ^ (Rc - Ra)) < 0)
{
return Rb;
- }
+ }
else if ((sgn ^ (Rb - Rc)) < 0)
{
return Ra;
}
- // default case, valid if Rc element of [Ra,Rb]
+ // default case, valid if Rc element of [Ra,Rb]
return Ra + Rb - Rc;
}
public:
- JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : STRATEGY(info),
+ JlsCodec(const TRAITS& inTraits, const JlsParameters& info) : STRATEGY(info),
traits(inTraits),
_rect(),
_width(0),
_RUNindex(0),
_pquant(0),
_bCompare(0)
-
+
{
if (Info().ilv == ILV_NONE)
{
Info().components = 1;
}
- }
+ }
void SetPresets(const JlsCustomParameters& presets)
InitParams(presets.T1 != 0 ? presets.T1 : presetDefault.T1,
presets.T2 != 0 ? presets.T2 : presetDefault.T2,
- presets.T3 != 0 ? presets.T3 : presetDefault.T3,
+ presets.T3 != 0 ? presets.T3 : presetDefault.T3,
presets.RESET != 0 ? presets.RESET : presetDefault.RESET);
- }
+ }
bool IsInterleaved()
signed char QuantizeGratientOrg(LONG Di);
inlinehint LONG QuantizeGratient(LONG Di)
- {
+ {
ASSERT(QuantizeGratientOrg(Di) == *(_pquant + Di));
- return *(_pquant + Di);
+ return *(_pquant + Di);
}
void InitQuantizationLUT();
-
+
LONG DecodeValue(LONG k, LONG limit, LONG qbpp);
inlinehint void EncodeMappedValue(LONG k, LONG mappedError, LONG limit);
{
LONG sign = BitWiseSign(Qs);
JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
- LONG k = ctx.GetGolomb();
- LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
+ LONG k = ctx.GetGolomb();
+ LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
LONG ErrVal;
const Code& code = decodingTables[k].Get(STRATEGY::PeekByte());
if (code.GetLength() != 0)
{
STRATEGY::Skip(code.GetLength());
- ErrVal = code.GetValue();
+ ErrVal = code.GetValue();
ASSERT(ABS(ErrVal) < 65535);
}
else
{
- ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp));
+ ErrVal = UnMapErrVal(DecodeValue(k, traits.LIMIT, traits.qbpp));
if (ABS(ErrVal) > 65535)
throw JlsException(InvalidCompressedData);
- }
+ }
ErrVal = ErrVal ^ ((traits.NEAR == 0) ? ctx.GetErrorCorrection(k) : 0);
- ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
+ ctx.UpdateVariables(ErrVal, traits.NEAR, traits.RESET);
ErrVal = ApplySign(ErrVal, sign);
- return traits.ComputeReconstructedSample(Px, ErrVal);
+ return traits.ComputeReconstructedSample(Px, ErrVal);
}
LONG sign = BitWiseSign(Qs);
JlsContext& ctx = _contexts[ApplySign(Qs, sign)];
LONG k = ctx.GetGolomb();
- LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
+ LONG Px = traits.CorrectPrediction(pred + ApplySign(ctx.C, sign));
LONG ErrVal = traits.ComputeErrVal(ApplySign(x - Px, sign));
size_t DecodeScan(void* rawData, const JlsRect& size, BYTE **buf, size_t *buf_size, size_t offset, bool bCompare);
protected:
- // codec parameters
+ // codec parameters
TRAITS traits;
JlsRect _rect;
int _width;
- LONG T1;
+ LONG T1;
LONG T2;
- LONG T3;
+ LONG T3;
// compression context
- JlsContext _contexts[365];
+ JlsContext _contexts[365];
CContextRunMode _contextRunmode[2];
LONG _RUNindex;
PIXEL* _previousLine; // previous line ptr
CTable table;
short nerr;
for (nerr = 0; ; nerr++)
- {
+ {
// Q is not used when k != 0
LONG merrval = GetMappedErrVal(nerr);//, k, -1);
OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
}
for (nerr = -1; ; nerr--)
- {
+ {
// Q is not used when k != 0
LONG merrval = GetMappedErrVal(nerr);//, k, -1);
OFPair<LONG, LONG> paircode = CreateEncodedValue(k, merrval);
if (highbits + 1 > 31)
{
STRATEGY::AppendToBitStream(0, highbits / 2);
- highbits = highbits - highbits / 2;
+ highbits = highbits - highbits / 2;
}
STRATEGY::AppendToBitStream(1, highbits + 1);
STRATEGY::AppendToBitStream((mappedError & ((1 << k) - 1)), k);
if (limit - traits.qbpp > 31)
{
STRATEGY::AppendToBitStream(0, 31);
- STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
+ STRATEGY::AppendToBitStream(1, limit - traits.qbpp - 31);
}
else
{
- STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
+ STRATEGY::AppendToBitStream(1, limit - traits.qbpp);
}
STRATEGY::AppendToBitStream((mappedError - 1) & ((1 << traits.qbpp) - 1), traits.qbpp);
}
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::InitQuantizationLUT()
{
- // for lossless mode with default parameters, we have precomputed te luts for bitcounts 8,10,12 and 16
+ // for lossless mode with default parameters, we have precomputed te luts for bitcounts 8,10,12 and 16
if (traits.NEAR == 0 && traits.MAXVAL == (1 << traits.bpp) - 1)
{
JlsCustomParameters presets = ComputeDefault(traits.MAXVAL, traits.NEAR);
if (presets.T1 == T1 && presets.T2 == T2 && presets.T3 == T3)
{
- if (traits.bpp == 8)
+ if (traits.bpp == 8)
{
- _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ];
+ _pquant = &rgquant8Ll[rgquant8Ll.size() / 2 ];
return;
}
- if (traits.bpp == 10)
+ if (traits.bpp == 10)
{
- _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ];
+ _pquant = &rgquant10Ll[rgquant10Ll.size() / 2 ];
return;
- }
- if (traits.bpp == 12)
+ }
+ if (traits.bpp == 12)
{
- _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ];
+ _pquant = &rgquant12Ll[rgquant12Ll.size() / 2 ];
return;
- }
- if (traits.bpp == 16)
+ }
+ if (traits.bpp == 16)
{
- _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ];
+ _pquant = &rgquant16Ll[rgquant16Ll.size() / 2 ];
return;
- }
- }
+ }
+ }
}
LONG RANGE = 1 << traits.bpp;
LONG JlsCodec<TRAITS,STRATEGY>::DecodeRIError(CContextRunMode& ctx)
{
LONG k = ctx.GetGolomb();
- LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, traits.qbpp);
+ LONG EMErrval = DecodeValue(k, traits.LIMIT - J[_RUNindex]-1, traits.qbpp);
LONG Errval = ctx.ComputeErrVal(EMErrval + ctx._nRItype, k);
ctx.UpdateVariables(Errval, EMErrval);
return Errval;
{
LONG k = ctx.GetGolomb();
bool map = ctx.ComputeMap(Errval, k);
- LONG EMErrval = 2 * ABS(Errval) - ctx._nRItype - map;
+ LONG EMErrval = 2 * ABS(Errval) - ctx._nRItype - map;
ASSERT(Errval == ctx.ComputeErrVal(EMErrval + ctx._nRItype, k));
EncodeMappedValue(k, EMErrval, traits.LIMIT-J[_RUNindex]-1);
template<class TRAITS, class STRATEGY>
Triplet<OFTypename TRAITS::SAMPLE> JlsCodec<TRAITS,STRATEGY>::DecodeRIPixel(Triplet<SAMPLE> Ra, Triplet<SAMPLE> Rb)
-{
+{
LONG Errval1 = DecodeRIError(_contextRunmode[0]);
LONG Errval2 = DecodeRIError(_contextRunmode[0]);
LONG Errval3 = DecodeRIError(_contextRunmode[0]);
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::EncodeRunPixels(LONG runLength, bool endOfLine)
{
- while (runLength >= LONG(1 << J[_RUNindex]))
+ while (runLength >= LONG(1 << J[_RUNindex]))
{
STRATEGY::AppendOnesToBitStream(1);
runLength = runLength - LONG(1 << J[_RUNindex]);
IncrementRunIndex();
}
- if (endOfLine)
+ if (endOfLine)
{
- if (runLength != 0)
+ if (runLength != 0)
{
- STRATEGY::AppendOnesToBitStream(1);
+ STRATEGY::AppendOnesToBitStream(1);
}
}
else
if (index != cpixelMac)
{
- // incomplete run
+ // incomplete run
index += (J[_RUNindex] > 0) ? STRATEGY::ReadValue(J[_RUNindex]) : 0;
}
for (LONG i = 0; i < index; ++i)
{
startPos[i] = Ra;
- }
+ }
return index;
}
LONG runLength = 0;
- while (traits.IsNear(ptypeCurX[runLength],Ra))
+ while (traits.IsNear(ptypeCurX[runLength],Ra))
{
ptypeCurX[runLength] = Ra;
runLength++;
LONG index = 0;
LONG Rb = _previousLine[index-1];
LONG Rd = _previousLine[index];
+ LONG RANGE_UPPER = 1 << traits.bpp;
+ LONG RANGE_LOWER = - RANGE_UPPER;
while(index < _width)
- {
+ {
LONG Ra = _currentLine[index -1];
LONG Rc = Rb;
Rb = Rd;
Rd = _previousLine[index + 1];
+ // make sure that values are not out of range
+ if ( (Rd - Rb < RANGE_LOWER) || (Rd - Rb > RANGE_UPPER)
+ || (Rb - Rc < RANGE_LOWER) || (Rb - Rc > RANGE_UPPER)
+ || (Rc - Ra < RANGE_LOWER) || (Rc - Ra > RANGE_UPPER))
+ {
+ throw JlsException(InvalidCompressedData);
+ }
+
LONG Qs = ComputeContextID(QuantizeGratient(Rd - Rb), QuantizeGratient(Rb - Rc), QuantizeGratient(Rc - Ra));
if (Qs != 0)
{
index += DoRunMode(index, (STRATEGY*)(NULL));
Rb = _previousLine[index-1];
- Rd = _previousLine[index];
- }
+ Rd = _previousLine[index];
+ }
}
}
{
LONG index = 0;
while(index < _width)
- {
+ {
Triplet<SAMPLE> Ra = _currentLine[index -1];
Triplet<SAMPLE> Rc = _previousLine[index-1];
Triplet<SAMPLE> Rb = _previousLine[index];
LONG Qs2 = ComputeContextID(QuantizeGratient(Rd.v2 - Rb.v2), QuantizeGratient(Rb.v2 - Rc.v2), QuantizeGratient(Rc.v2 - Ra.v2));
LONG Qs3 = ComputeContextID(QuantizeGratient(Rd.v3 - Rb.v3), QuantizeGratient(Rb.v3 - Rc.v3), QuantizeGratient(Rc.v3 - Ra.v3));
-
+
if (Qs1 == 0 && Qs2 == 0 && Qs3 == 0)
{
index += DoRunMode(index, (STRATEGY*)(NULL));
Rx.v3 = DoRegular(Qs3, _currentLine[index].v3, GetPredictedValue(Ra.v3, Rb.v3, Rc.v3), (STRATEGY*)(NULL));
_currentLine[index] = Rx;
index++;
- }
+ }
}
}
-// DoScan: Encodes or decodes a scan.
+// DoScan: Encodes or decodes a scan.
// In ILV_SAMPLE mode, multiple components are handled in DoLine
// In ILV_LINE mode, a call do DoLine is made for every component
-// In ILV_NONE mode, DoScan is called for each component
+// In ILV_NONE mode, DoScan is called for each component
template<class TRAITS, class STRATEGY>
void JlsCodec<TRAITS,STRATEGY>::DoScan(BYTE **ptr, size_t *size, size_t offset)
-{
+{
_width = Info().width;
STRATEGY::Init(ptr, size, offset);
OFVector<PIXEL> vectmp(2 * components * pixelstride);
OFVector<LONG> rgRUNindex(components);
-
+
for (LONG line = 0; line < Info().height; ++line)
{
- _previousLine = &vectmp[1];
- _currentLine = &vectmp[1 + components * pixelstride];
+ _previousLine = &vectmp[1];
+ _currentLine = &vectmp[1 + components * pixelstride];
if ((line & 1) == 1)
{
PIXEL *tmp = _previousLine;
for (int component = 0; component < components; ++component)
{
_RUNindex = rgRUNindex[component];
-
+
// initialize edge pixels used for prediction
_previousLine[_width] = _previousLine[_width - 1];
_currentLine[-1] = _previousLine[0];
DoLine((PIXEL*) NULL); // dummy arg for overload resolution
-
+
rgRUNindex[component] = _RUNindex;
_previousLine += pixelstride;
_currentLine += pixelstride;
}
-
+
if (_rect.Y <= line && line < _rect.Y + _rect.Height)
{
STRATEGY::OnLineEnd(_rect.Width, _currentLine + _rect.X - (components * pixelstride), pixelstride);
return new PostProcesSingleComponent(pvoidOut, Info(), sizeof(typename TRAITS::PIXEL));
if (Info().colorTransform == 0)
- return new ProcessTransformed<TransformNone<OFTypename TRAITS::SAMPLE> >(pvoidOut, Info(), TransformNone<SAMPLE>());
+ return new ProcessTransformed<TransformNone<OFTypename TRAITS::SAMPLE> >(pvoidOut, Info(), TransformNone<SAMPLE>());
if (Info().bitspersample == sizeof(SAMPLE)*8)
{
case COLORXFORM_HP3 : return new ProcessTransformed<TransformHp3<SAMPLE> >(pvoidOut, Info(), TransformHp3<SAMPLE>()); break;
default: throw JlsException(UnsupportedColorTransform);
}
- }
+ }
else if (Info().bitspersample > 8)
{
int shift = 16 - Info().bitspersample;
}
DoScan(ptr, size, offset);
-
+
return STRATEGY::GetLength();
}
_rect = rect;
DoScan(ptr, size, offset + readBytes);
-
+
return STRATEGY::GetCurBytePos() - (*ptr + offset);
}
-//
-// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
-//
+//
+// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
+//
#ifndef CHARLS_STREAMS
#define CHARLS_STREAMS
-// This file defines JPEG-LS streams: The header and the actual pixel data. Header markers have fixed length, the pixeldata not.
+// This file defines JPEG-LS streams: The header and the actual pixel data. Header markers have fixed length, the pixeldata not.
enum JPEGLS_ColorXForm
{
- // default (RGB)
- COLORXFORM_NONE = 0,
+ // default (RGB)
+ COLORXFORM_NONE = 0,
- // Color transforms as defined by HP
- COLORXFORM_HP1,
- COLORXFORM_HP2,
- COLORXFORM_HP3,
+ // Color transforms as defined by HP
+ COLORXFORM_HP1,
+ COLORXFORM_HP2,
+ COLORXFORM_HP3,
- // Defined by HP but not supported by CharLS
- COLORXFORM_RGB_AS_YUV_LOSSY,
- COLORXFORM_MATRIX
+ // Defined by HP but not supported by CharLS
+ COLORXFORM_RGB_AS_YUV_LOSSY,
+ COLORXFORM_MATRIX
};
-
+
//
// JLSOutputStream: minimal implementation to write JPEG header streams
//
class JLSOutputStream
{
- friend class JpegMarkerSegment;
- friend class JpegImageDataSegment;
+ friend class JpegMarkerSegment;
+ friend class JpegImageDataSegment;
public:
- JLSOutputStream();
- virtual ~JLSOutputStream();
+ JLSOutputStream();
+ virtual ~JLSOutputStream();
- void Init(Size size, LONG bitsPerSample, LONG ccomp);
- void AddScan(const void* compareData, const JlsParameters* pparams);
- void AddLSE(const JlsCustomParameters* pcustom);
- void AddColorTransform(int i);
- size_t GetBytesWritten()
- { return _cbytesWritten; }
+ void Init(Size size, LONG bitsPerSample, LONG ccomp);
+ void AddScan(const void* compareData, const JlsParameters* pparams);
+ void AddLSE(const JlsCustomParameters* pcustom);
+ void AddColorTransform(int i);
+ size_t GetBytesWritten()
+ { return _cbytesWritten; }
- size_t Write(BYTE **ptr, size_t *size, size_t offset);
+ size_t Write(BYTE **ptr, size_t *size, size_t offset);
- BYTE **get_pos() { return _position; }
+ BYTE **get_pos() { return _position; }
- size_t *get_size() { return _size; }
+ size_t *get_size() { return _size; }
- size_t get_offset() { return _current_offset; }
+ size_t get_offset() { return _current_offset; }
- void EnableCompare(bool bCompare)
- { _bCompare = bCompare; }
+ void EnableCompare(bool bCompare)
+ { _bCompare = bCompare; }
private:
- void WriteByte(BYTE val)
- {
- ASSERT(!_bCompare || (*_position)[_current_offset] == val);
-
- if (_current_offset == *_size) {
- *_position = re_alloc(*_position, _size);
- }
-
- (*_position)[_current_offset++] = val;
-
- _cbytesWritten++;
- }
-
- void WriteBytes(const OFVector<BYTE>& rgbyte)
- {
- for (size_t i = 0; i < rgbyte.size(); ++i)
- {
- WriteByte(rgbyte[i]);
- }
- }
-
- void WriteWord(USHORT val)
- {
- WriteByte(BYTE(val / 0x100));
- WriteByte(BYTE(val % 0x100));
- }
-
- void seek(size_t n)
- {
- _cbytesWritten += n;
- _current_offset += n;
- }
-
- bool _bCompare;
+ void WriteByte(BYTE val)
+ {
+ ASSERT(!_bCompare || (*_position)[_current_offset] == val);
+
+ if (_current_offset == *_size) {
+ *_position = re_alloc(*_position, _size);
+ }
+
+ (*_position)[_current_offset++] = val;
+
+ _cbytesWritten++;
+ }
+
+ void WriteBytes(const OFVector<BYTE>& rgbyte)
+ {
+ for (size_t i = 0; i < rgbyte.size(); ++i)
+ {
+ WriteByte(rgbyte[i]);
+ }
+ }
+
+ void WriteWord(USHORT val)
+ {
+ WriteByte(BYTE(val / 0x100));
+ WriteByte(BYTE(val % 0x100));
+ }
+
+ void seek(size_t n)
+ {
+ _cbytesWritten += n;
+ _current_offset += n;
+ }
+
+ bool _bCompare;
private:
- static BYTE *re_alloc(BYTE *old_ptr, size_t *old_size)
- {
- size_t new_size = *old_size * 2;
-#ifdef HAVE_STD__NOTHROW
- BYTE *new_ptr = new BYTE[new_size];
-#else
- BYTE *new_ptr = new BYTE[new_size];
-#endif
- if (new_ptr == NULL) {
- throw alloc_fail();
- }
+ static BYTE *re_alloc(BYTE *old_ptr, size_t *old_size)
+ {
+ size_t new_size = *old_size * 2;
+ BYTE *new_ptr = new(std::nothrow) BYTE[new_size];
+ if (new_ptr == NULL) {
+ throw alloc_fail();
+ }
- OFBitmanipTemplate<BYTE>::copyMem(old_ptr, new_ptr, *old_size);
+ OFBitmanipTemplate<BYTE>::copyMem(old_ptr, new_ptr, *old_size);
- delete[] old_ptr;
+ delete[] old_ptr;
- *old_size = new_size;
+ *old_size = new_size;
- return new_ptr;
- }
+ return new_ptr;
+ }
- BYTE **_position;
- size_t *_size;
- size_t _current_offset;
- size_t _cbytesWritten;
- LONG _icompLast;
- OFVector<JpegSegment*> _segments;
+ BYTE **_position;
+ size_t *_size;
+ size_t _current_offset;
+ size_t _cbytesWritten;
+ LONG _icompLast;
+ OFVector<JpegSegment*> _segments;
};
class JLSInputStream
{
public:
- JLSInputStream(const BYTE* pdata, size_t cbyteLength);
+ JLSInputStream(const BYTE* pdata, size_t cbyteLength);
+
+ size_t GetBytesRead()
+ { return _cbyteOffset; }
- size_t GetBytesRead()
- { return _cbyteOffset; }
+ const JlsParameters& GetMetadata() const
+ { return _info; }
- const JlsParameters& GetMetadata() const
- { return _info; }
+ const JlsCustomParameters& GetCustomPreset() const
+ { return _info.custom; }
- const JlsCustomParameters& GetCustomPreset() const
- { return _info.custom; }
+ void Read(void* pvoid, size_t cbyteAvailable);
+ void ReadHeader();
- void Read(void* pvoid, size_t cbyteAvailable);
- void ReadHeader();
-
- void EnableCompare(bool bCompare)
- { _bCompare = bCompare; }
+ void EnableCompare(bool bCompare)
+ { _bCompare = bCompare; }
- void SetInfo(JlsParameters* info) { _info = *info; }
+ void SetInfo(JlsParameters* info) { _info = *info; }
- void SetRect(JlsRect rect) { _rect = rect; }
+ void SetRect(JlsRect rect) { _rect = rect; }
private:
- void ReadPixels(void* pvoid, size_t cbyteAvailable);
- void ReadScan(void*);
- void ReadStartOfScan();
- void ReadPresetParameters();
- void ReadComment();
- void ReadStartOfFrame();
- BYTE ReadByte();
- int ReadWord();
- void ReadNBytes(OFVector<char>& dst, int byteCount);
-
- // JFIF
- void ReadJfif();
- // Color Transform Application Markers & Code Stream (HP extension)
- void ReadColorSpace();
- void ReadColorXForm();
-
+ void ReadPixels(void* pvoid, size_t cbyteAvailable);
+ void ReadScan(void*);
+ void ReadStartOfScan();
+ void ReadPresetParameters();
+ void ReadComment();
+ void ReadStartOfFrame();
+ BYTE ReadByte();
+ int ReadWord();
+ void ReadNBytes(OFVector<char>& dst, int byteCount);
+
+ // JFIF
+ void ReadJfif();
+ // Color Transform Application Markers & Code Stream (HP extension)
+ void ReadColorSpace();
+ void ReadColorXForm();
+
private:
- const BYTE* _pdata;
- size_t _cbyteOffset;
- size_t _cbyteLength;
- bool _bCompare;
- JlsParameters _info;
- JlsRect _rect;
+ const BYTE* _pdata;
+ size_t _cbyteOffset;
+ size_t _cbyteLength;
+ bool _bCompare;
+ JlsParameters _info;
+ JlsRect _rect;
};
/*
*
- * Copyright (C) 2007-2024, OFFIS e.V.
+ * Copyright (C) 2007-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
+Uint16 DJLSDecoderBase::decodedBitsAllocated(
+ Uint16 /* bitsAllocated */,
+ Uint16 bitsStored) const
+{
+ // this codec does not support images with less than 2 bits per sample
+ if (bitsStored < 2) return 0;
+
+ // for images with 2..8 bits per sample, BitsAllocated will be 8
+ if (bitsStored <= 8) return 8;
+
+ // for images with 9..16 bits per sample, BitsAllocated will be 16
+ if (bitsStored <= 16) return 16;
+
+ // this codec does not support images with more than 16 bits per sample
+ return 0;
+}
+
+
OFCondition DJLSDecoderBase::decode(
const DcmRepresentationParameter * /* fromRepParam */,
DcmPixelSequence * pixSeq,
{
DCMJPLS_DEBUG("JPEG-LS decoder processes frame " << (currentFrame+1));
- result = decodeFrame(pixSeq, djcp, dataset, currentFrame, currentItem, pixeldata8, frameSize,
+ result = decodeFrameNoSwap(pixSeq, djcp, dataset, currentFrame, currentItem, pixeldata8, frameSize,
imageFrames, imageColumns, imageRows, imageSamplesPerPixel, bytesPerSample);
// check if we should enforce "one fragment per frame" while
result = ((DcmItem *)dataset)->putAndInsertString(DCM_NumberOfFrames, numBuf);
}
+ if (result.good())
+ {
+ // decompression is complete, finally adjust byte order if necessary
+ if (bytesPerSample == 1) // we're writing bytes into words
+ {
+ result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, pixeldata16, OFstatic_cast(Uint32, totalSize), sizeof(Uint16));
+ }
+ }
+
if (result.good() && (dataset->ident() == EVR_dataset))
{
DcmItem *ditem = OFreinterpret_cast(DcmItem*, dataset);
return result;
}
-OFCondition DJLSDecoderBase::decodeFrame(
+OFCondition DJLSDecoderBase::decodeFrameNoSwap(
DcmPixelSequence * fromPixSeq,
const DJLSCodecParameter *cp,
DcmItem *dataset,
}
}
- if (result.good())
- {
- // decompression is complete, finally adjust byte order if necessary
- if (bytesPerSample == 1) // we're writing bytes into words
- {
- result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, buffer,
- bufSize, sizeof(Uint16));
- }
- }
-
// update planar configuration if we are decoding a color image
if (result.good() && (imageSamplesPerPixel > 1))
{
return result;
}
+OFCondition DJLSDecoderBase::decodeFrame(
+ DcmPixelSequence * fromPixSeq,
+ const DJLSCodecParameter *cp,
+ DcmItem *dataset,
+ Uint32 frameNo,
+ Uint32& currentItem,
+ void * buffer,
+ Uint32 bufSize,
+ Sint32 imageFrames,
+ Uint16 imageColumns,
+ Uint16 imageRows,
+ Uint16 imageSamplesPerPixel,
+ Uint16 bytesPerSample)
+{
+ OFCondition result = decodeFrameNoSwap(fromPixSeq, cp, dataset, frameNo, currentItem, buffer, bufSize, imageFrames, imageColumns, imageRows, imageSamplesPerPixel, bytesPerSample);
+ if (result.good())
+ {
+ // decompression is complete, finally adjust byte order if necessary
+ if (bytesPerSample == 1) // we're writing bytes into words
+ {
+ if ((gLocalByteOrder == EBO_BigEndian) && (bufSize & 1))
+ {
+ DCMJPLS_WARN("Size of frame buffer is odd, cannot correct byte order for last pixel value");
+ }
+ result = swapIfNecessary(gLocalByteOrder, EBO_LittleEndian, buffer, bufSize, sizeof(Uint16));
+ }
+ }
+ return result;
+}
OFCondition DJLSDecoderBase::encode(
const Uint16 * /* pixelData */,
/*
*
- * Copyright (C) 2007-2024, OFFIS e.V.
+ * Copyright (C) 2007-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "intrface.h"
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_RDONLY */
-#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* required for sys/stat.h */
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for stat, fstat */
-#endif
END_EXTERN_C
}
+Uint16 DJLSEncoderBase::decodedBitsAllocated(
+ Uint16 /* bitsAllocated */,
+ Uint16 /* bitsStored */) const
+{
+ return 0;
+}
+
+
OFCondition DJLSEncoderBase::decode(
const DcmRepresentationParameter * /* fromRepParam */,
DcmPixelSequence * /* pixSeq */,
jls_params.width = width;
jls_params.allowedlossyerror = 0; // must be zero for raw mode
jls_params.outputBgr = false;
- // No idea what this one does, but I don't think DICOM says anything about it
+ // color transformation is a non-standard HP/JPEG-LS extension
jls_params.colorTransform = 0;
// Unset: jls_params.jfif (thumbnail, dpi)
case EPR_Sint8:
{
// image representation is 8 bit signed or unsigned
+ Uint8 mask = 0xFF >> (8-depth);
if (samplesPerPixel == 1)
{
const Uint8 *yv = OFreinterpret_cast(const Uint8 *, planes[0]) + framesize * frame;
buffer_size = framesize;
buffer = new Uint8[buffer_size];
- memcpy(buffer, yv, framesize);
+ for (size_t i=0; i < framesize; ++i)
+ {
+ buffer[i] = *yv & mask;
+ yv++;
+ }
}
else
{
{
for (int col=width; col; --col)
{
- buffer[i++] = *rv;
- buffer[i++] = *gv;
- buffer[i++] = *bv;
+ buffer[i++] = *rv & mask;
+ buffer[i++] = *gv & mask;
+ buffer[i++] = *bv & mask;
rv++;
gv++;
case EPR_Sint16:
{
// image representation is 16 bit signed or unsigned
+ Uint16 mask = 0xFFFF >> (16-depth);
if (samplesPerPixel == 1)
{
const Uint16 *yv = OFreinterpret_cast(const Uint16 *, planes[0]) + framesize * frame;
- buffer_size = framesize*sizeof(Uint16);
- buffer = new Uint8[buffer_size];
- memcpy(buffer, yv, buffer_size);
+
+ buffer_size = framesize;
+ Uint16 *buffer16 = new Uint16[buffer_size];
+ buffer = OFreinterpret_cast(Uint8 *, buffer16);
+
+ // Convert to byte count
+ buffer_size *= 2;
+
+ for (size_t i=0; i < framesize; ++i)
+ {
+ buffer16[i] = *yv & mask;
+ yv++;
+ }
}
else
{
{
for (int col=width; col; --col)
{
- buffer16[i++] = *rv;
- buffer16[i++] = *gv;
- buffer16[i++] = *bv;
+ buffer16[i++] = *rv & mask;
+ buffer16[i++] = *gv & mask;
+ buffer16[i++] = *bv & mask;
rv++;
gv++;
jls_params.allowedlossyerror = nearLosslessDeviation;
jls_params.outputBgr = false;
jls_params.bitspersample = depth;
- // No idea what this one does, but I don't think DICOM says anything about it
+ // color transformation is a non-standard HP/JPEG-LS extension
jls_params.colorTransform = 0;
// This was already checked for a sane value above
{
// 'compressed_buffer_size' now contains the size of the compressed data in buffer
compressedSize = OFstatic_cast(unsigned long, bytesWritten);
- fixPaddingIfNecessary(OFstatic_cast(Uint8 *, buffer), compressed_buffer_size, compressedSize, djcp->getUseFFbitstreamPadding());
+ fixPaddingIfNecessary(OFstatic_cast(Uint8 *, compressed_buffer), compressed_buffer_size, compressedSize, djcp->getUseFFbitstreamPadding());
result = pixelSequence->storeCompressedFrame(offsetList, compressed_buffer, compressedSize, fragmentSize);
}
endif()
# make sure executables are linked to the corresponding libraries
-foreach(PROGRAM dcmrecv dcmsend echoscu findscu getscu movescu storescp storescu termscu)
- DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmnet dcmdata oflog ofstd)
+foreach(PROGRAM dcmsend termscu)
+ DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmnet)
endforeach()
-foreach(PROGRAM dcmrecv echoscu findscu storescp storescu getscu)
+foreach(PROGRAM dcmrecv echoscu findscu storescp storescu getscu movescu)
DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmtls)
endforeach()
../../dcmdata/include/dcmtk/dcmdata/dcmetinf.h \
../../dcmdata/include/dcmtk/dcmdata/dcdicent.h \
../../dcmdata/include/dcmtk/dcmdata/dcostrmz.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h
+ ../../dcmdata/include/dcmtk/dcmdata/dcostrma.h \
+ ../../dcmtls/include/dcmtk/dcmtls/tlsopt.h \
+ ../../dcmtls/include/dcmtk/dcmtls/tlslayer.h \
+ ../include/dcmtk/dcmnet/dcmlayer.h \
+ ../../dcmtls/include/dcmtk/dcmtls/tlsdefin.h \
+ ../../dcmtls/include/dcmtk/dcmtls/tlsciphr.h
storescp.o: storescp.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
$(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(DCMTLSLIBS) $(OPENSSLLIBS) $(LIBS)
movescu: movescu.o
- $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS)
+ $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(DCMTLSLIBS) $(OPENSSLLIBS) $(LIBS)
termscu: termscu.o
$(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $@.o $(LOCALLIBS) $(LIBS)
/*
*
- * Copyright (C) 2013-2024, OFFIS e.V.
+ * Copyright (C) 2013-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
cmd.addOption("--verbose-pc", "+v", "show presentation contexts in verbose mode");
cmd.addGroup("network options:");
+ cmd.addSubGroup("IP protocol version:");
+ cmd.addOption("--ipv4", "-i4", "use IPv4 only (default)");
+ cmd.addOption("--ipv6", "-i6", "use IPv6 only");
+ cmd.addOption("--ip-auto", "-i0", "use IPv6/IPv4 dual stack");
+
cmd.addSubGroup("association negotiation profile from configuration file:");
cmd.addOption("--config-file", "-xf", 2, "[f]ilename, [p]rofile: string",
"use profile p from configuration file f");
return EXITCODE_NO_ERROR;
}
- // check if the command line contains the --list-profiles option
+ /* check if the command line contains the --list-profiles option */
if (tlsOptions.listOfProfilesRequested(cmd))
{
tlsOptions.printSupportedTLSProfiles(app, COUT);
}
/* network options */
+
+ /* set the IP protocol version */
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--ipv4"))
+ dcmIncomingProtocolFamily.set(ASC_AF_INET);
+ if (cmd.findOption("--ipv6"))
+ dcmIncomingProtocolFamily.set(ASC_AF_INET6);
+ if (cmd.findOption("--ip-auto"))
+ dcmIncomingProtocolFamily.set(ASC_AF_UNSPEC);
+ cmd.endOptionBlock();
+
if (cmd.findOption("--config-file"))
{
app.checkValue(cmd.getValue(opt_configFile));
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
UID_JPEGProcess14SV1TransferSyntax,
UID_RLELosslessTransferSyntax,
UID_DeflatedExplicitVRLittleEndianTransferSyntax,
+ UID_DeflatedImageFrameCompressionTransferSyntax,
UID_JPEGLSLosslessTransferSyntax,
UID_JPEGLSLossyTransferSyntax,
UID_JPEG2000LosslessOnlyTransferSyntax,
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dcdicent.h"
#include "dcmtk/dcmdata/dcostrmz.h" /* for dcmZlibCompressionLevel */
#include "dcmtk/ofstd/ofstd.h"
+#include "dcmtk/dcmtls/tlsopt.h" /* for DcmTLSOptions */
#ifdef WITH_ZLIB
#include <zlib.h> /* for zlibVersion() */
#define EXITCODE_CANNOT_CLOSE_ASSOCIATION 67
#define EXITCODE_CMOVE_WARNING 68
#define EXITCODE_CMOVE_ERROR 69
-
+#define EXITCODE_CANNOT_CREATE_TLS_LAYER 70
typedef enum {
QMPatientRoot = 0,
}
}
-static OFCondition cmove(T_ASC_Association *assoc, const char *fname);
+static OFCondition cmove(T_ASC_Association *assoc, const char *fname, OFBool secureConnection);
static OFCondition
addPresentationContext(T_ASC_Parameters *params,
const char *opt_peerTitle = PEERAPPLICATIONTITLE;
const char *opt_ourTitle = APPLICATIONTITLE;
OFList<OFString> fileNameList;
+ DcmTLSOptions tlsOptions(NET_ACCEPTORREQUESTOR);
OFStandard::initializeNetwork();
OFLog::addOptions(cmd);
cmd.addGroup("network options:");
+ cmd.addSubGroup("IP protocol version:");
+ cmd.addOption("--ipv4", "-i4", "use IPv4 only (default)");
+ cmd.addOption("--ipv6", "-i6", "use IPv6 only");
+ cmd.addOption("--ip-auto", "-i0", "use IPv6/IPv4 dual stack");
cmd.addSubGroup("override matching keys:");
cmd.addOption("--key", "-k", 1, "[k]ey: gggg,eeee=\"str\" or dict. name=\"str\"",
"override matching key");
cmd.addOption("--cancel", 1, "[n]umber: integer",
"cancel after n responses (default: never)");
cmd.addOption("--uid-padding", "-up", "silently correct space-padded UIDs");
+
+ // add TLS specific command line options if (and only if) we are compiling with OpenSSL
+ tlsOptions.addTLSCommandlineOptions(cmd);
+
cmd.addGroup("output options:");
cmd.addSubGroup("general:");
cmd.addOption("--output-directory", "-od", 1, "[d]irectory: string (default: \".\")", "write received objects to existing directory d");
{
app.printHeader(OFTrue /*print host identifier*/);
COUT << OFendl << "External libraries used:";
-#if !defined(WITH_ZLIB) && !defined(WITH_TCPWRAPPER)
+#if !defined(WITH_ZLIB) && !defined(WITH_TCPWRAPPER) && !defined(WITH_OPENSSL)
COUT << " none" << OFendl;
#else
COUT << OFendl;
#ifdef WITH_TCPWRAPPER
COUT << "- LIBWRAP" << OFendl;
#endif
+ // print OpenSSL version if (and only if) we are compiling with OpenSSL
+ tlsOptions.printLibraryVersion();
return EXITCODE_NO_ERROR;
}
}
+ // check if the command line contains the --list-ciphers option
+ if (tlsOptions.listOfCiphersRequested(cmd))
+ {
+ tlsOptions.printSupportedCiphersuites(app, COUT);
+ return EXITCODE_NO_ERROR;
+ }
+
+ // check if the command line contains the --list-profiles option
+ if (tlsOptions.listOfProfilesRequested(cmd))
+ {
+ tlsOptions.printSupportedTLSProfiles(app, COUT);
+ return EXITCODE_NO_ERROR;
+ }
+
/* command line parameters */
cmd.getParam(1, opt_peer);
#endif
cmd.endOptionBlock();
+ // set the IP protocol version
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--ipv4")) dcmIncomingProtocolFamily.set(ASC_AF_INET);
+ if (cmd.findOption("--ipv6")) dcmIncomingProtocolFamily.set(ASC_AF_INET6);
+ if (cmd.findOption("--ip-auto")) dcmIncomingProtocolFamily.set(ASC_AF_UNSPEC);
+ cmd.endOptionBlock();
+
#ifdef WITH_TCPWRAPPER
cmd.beginOptionBlock();
if (cmd.findOption("--access-full")) dcmTCPWrapperDaemonName.set(NULL);
if (cmd.findOption("--cancel")) app.checkValue(cmd.getValueAndCheckMin(opt_cancelAfterNResponses, 0));
if (cmd.findOption("--uid-padding")) opt_correctUIDPadding = OFTrue;
+ // evaluate (most of) the TLS command line options (if we are compiling with OpenSSL)
+ tlsOptions.parseArguments(app, cmd);
+
if (cmd.findOption("--output-directory"))
{
app.checkDependence("--output-directory", "--port", opt_retrievePort > 0);
}
ASC_setAPTitles(params, opt_ourTitle, opt_peerTitle, NULL);
+ // use the same network protocol family for incoming and outgoing connections
+ ASC_setProtocolFamily(params, dcmIncomingProtocolFamily.get());
+
OFStandard::snprintf(peerHost, sizeof(peerHost), "%s:%d", opt_peer, OFstatic_cast(int, opt_port));
ASC_setPresentationAddresses(params, OFStandard::getHostName().c_str(), peerHost);
+ OFBool secureConnection = tlsOptions.secureConnectionRequested();
+
+ /* create a secure transport layer if requested and OpenSSL is available */
+ cond = tlsOptions.createTransportLayer(net, params, app, cmd);
+ if (cond.bad()) {
+ OFLOG_FATAL(movescuLogger, DimseCondition::dump(temp_str, cond));
+ return EXITCODE_CANNOT_CREATE_TLS_LAYER;
+ }
+
/*
* We also add a presentation context for the corresponding
* find sop class.
if (fileNameList.empty())
{
/* no files provided on command line */
- cond = cmove(assoc, NULL);
+ cond = cmove(assoc, NULL, secureConnection);
} else {
OFListIterator(OFString) iter = fileNameList.begin();
OFListIterator(OFString) enditer = fileNameList.end();
while ((iter != enditer) && cond.good())
{
- cond = cmove(assoc, (*iter).c_str());
+ cond = cmove(assoc, (*iter).c_str(), secureConnection);
++iter;
}
}
OFStandard::shutdownNetwork();
+ cond = tlsOptions.writeRandomSeed();
+ if (cond.bad()) {
+ // failure to write back the random seed is a warning, not an error
+ OFLOG_WARN(movescuLogger, DimseCondition::dump(temp_str, cond));
+ }
+
return cmove_status_code;
}
}
static OFCondition
-acceptSubAssoc(T_ASC_Network *aNet, T_ASC_Association **assoc)
+acceptSubAssoc(T_ASC_Network *aNet, T_ASC_Association **assoc, OFBool secureConnection)
{
const char *knownAbstractSyntaxes[] = {
UID_VerificationSOPClass
const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 10
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 20
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 30
- NULL, NULL, NULL, NULL, NULL }; // +5
+ NULL, NULL, NULL, NULL, NULL, NULL }; // +6
int numTransferSyntaxes;
OFString temp_str;
- OFCondition cond = ASC_receiveAssociation(aNet, assoc, opt_maxPDU);
+ OFCondition cond = ASC_receiveAssociation(aNet, assoc, opt_maxPDU, NULL, NULL, secureConnection);
if (cond.good())
{
OFLOG_INFO(movescuLogger, "Sub-Association Received");
transferSyntaxes[27] = UID_JPEGXLLosslessTransferSyntax;
transferSyntaxes[28] = UID_JPEGXLJPEGRecompressionTransferSyntax;
transferSyntaxes[29] = UID_JPEGXLTransferSyntax;
- transferSyntaxes[30] = UID_DeflatedExplicitVRLittleEndianTransferSyntax;
- transferSyntaxes[31] = UID_EncapsulatedUncompressedExplicitVRLittleEndianTransferSyntax;
+ transferSyntaxes[30] = UID_DeflatedImageFrameCompressionTransferSyntax;
+ transferSyntaxes[31] = UID_DeflatedExplicitVRLittleEndianTransferSyntax;
+ transferSyntaxes[32] = UID_EncapsulatedUncompressedExplicitVRLittleEndianTransferSyntax;
if (gLocalByteOrder == EBO_LittleEndian)
{
- transferSyntaxes[32] = UID_LittleEndianExplicitTransferSyntax;
- transferSyntaxes[33] = UID_BigEndianExplicitTransferSyntax;
- } else {
- transferSyntaxes[32] = UID_BigEndianExplicitTransferSyntax;
transferSyntaxes[33] = UID_LittleEndianExplicitTransferSyntax;
+ transferSyntaxes[34] = UID_BigEndianExplicitTransferSyntax;
+ } else {
+ transferSyntaxes[33] = UID_BigEndianExplicitTransferSyntax;
+ transferSyntaxes[34] = UID_LittleEndianExplicitTransferSyntax;
}
- transferSyntaxes[34] = UID_LittleEndianImplicitTransferSyntax;
- numTransferSyntaxes = 35;
+ transferSyntaxes[35] = UID_LittleEndianImplicitTransferSyntax;
+ numTransferSyntaxes = 36;
} else {
/* We prefer explicit transfer syntaxes.
* If we are running on a Little Endian machine we prefer
}
static void
-subOpCallback(void * /*subOpCallbackData*/ ,
+subOpCallback(void *subOpCallbackData,
T_ASC_Network *aNet, T_ASC_Association **subAssoc)
{
-
if (aNet == NULL) return; /* help no net ! */
+ OFBool secureConnection = OFFalse;
+ if (subOpCallbackData) {
+ secureConnection = * OFreinterpret_cast(OFBool *, subOpCallbackData);
+ }
+
if (*subAssoc == NULL) {
/* negotiate association */
- acceptSubAssoc(aNet, subAssoc);
+ acceptSubAssoc(aNet, subAssoc, secureConnection);
} else {
/* be a service class provider */
subOpSCP(subAssoc);
static OFCondition
-moveSCU(T_ASC_Association *assoc, const char *fname)
+moveSCU(T_ASC_Association *assoc, const char *fname, OFBool secureConnection)
{
T_ASC_PresentationContextID presId;
T_DIMSE_C_MoveRQ req;
OFCondition cond = DIMSE_moveUser(assoc, presId, &req, dcmff.getDataset(),
moveCallback, &callbackData, opt_blockMode, opt_dimse_timeout, net, subOpCallback,
- NULL, &rsp, &statusDetail, &rspIds, opt_ignorePendingDatasets);
+ &secureConnection, &rsp, &statusDetail, &rspIds, opt_ignorePendingDatasets);
if (cond == EC_Normal) {
static OFCondition
-cmove(T_ASC_Association *assoc, const char *fname)
+cmove(T_ASC_Association *assoc, const char *fname, OFBool secureConnection)
{
OFCondition cond = EC_Normal;
int n = OFstatic_cast(int, opt_repeatCount);
while (cond.good() && n--)
- cond = moveSCU(assoc, fname);
+ cond = moveSCU(assoc, fname, secureConnection);
return cond;
}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* needed on Solaris for O_RDONLY */
-#endif
// On Solaris with Sun Workshop 11, <signal.h> declares signal() but <csignal> does not
#include <signal.h>
#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/ofstd/ofconapp.h"
#include "dcmtk/ofstd/ofbmanip.h" /* for OFBitmanipTemplate */
+#include "dcmtk/ofstd/oflist.h"
#include "dcmtk/ofstd/ofdatime.h"
#include "dcmtk/dcmnet/dicom.h" /* for DICOM_APPLICATION_ACCEPTOR */
#include "dcmtk/dcmnet/dimse.h"
ESM_PatientName
};
+#ifdef WIN32
+struct ChildProcessData
+{
+ HANDLE processHandle;
+ HANDLE waitHandle;
+ bool done;
+};
+
+OFList< ChildProcessData * > ChildProcessList;
+HANDLE ChildProcessEvent = NULL;
+
+// This callback function will be executed by Windows in a separate thread when
+// a child process has ended, similar to the SIGCHLD callback on Posix systems
+static void CALLBACK onExitedCallback(void* context, BOOLEAN /* isTimeOut */)
+{
+ // mark the related entry for the client process that has ended as "done", i.e. ready for clean-up
+ bool *done = OFstatic_cast(bool *, context);
+ *done = true;
+
+ // if the main thread is in a blocking wait in cleanChildren() because
+ // the maximum number of child processes was running, let the main thread continue now
+ if (ChildProcessEvent) SetEvent(ChildProcessEvent);
+}
+
+// This callback function will be called in the main thread by receiveTransportConnectionTCP()
+// whenever a new child process has been create by CreateProcessA().
+// The context parameter is a pointer to the process handle, which we must store
+// and close when not needed anymore.
+static void processCreatedCallback(void *context)
+{
+ // event handler for blocking wait in cleanChildren()
+ if (ChildProcessEvent == NULL) ChildProcessEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
+
+ // create new entry in list of child processes
+ ChildProcessData *cbd = new ChildProcessData();
+ cbd->processHandle = OFstatic_cast(HANDLE, context);
+ cbd->done = false;
+
+ // request Windows to call onExitedCallback() when the child process with the given process handle has exited
+ if (RegisterWaitForSingleObject(&cbd->waitHandle, cbd->processHandle, onExitedCallback, &cbd->done, INFINITE, WT_EXECUTEONLYONCE))
+ {
+ ChildProcessList.push_back(cbd);
+ }
+ else
+ {
+ OFLOG_WARN(storescpLogger, "RegisterWaitForSingleObject() failed, unable to track child process");
+ CloseHandle(cbd->processHandle);
+ delete cbd;
+ }
+}
+
+#endif
+
OFBool opt_showPresentationContexts = OFFalse;
OFBool opt_uniqueFilenames = OFFalse;
OFString opt_fileNameExtension;
OFBool opt_forkedChild = OFFalse;
OFBool opt_execSync = OFFalse; // default: execute in background
-
+volatile size_t numChildren = 0;
+OFCmdUnsignedInt opt_maxChildren = OFstatic_cast(OFCmdUnsignedInt, -1);
#ifdef HAVE_WAITPID
+
/** signal handler for SIGCHLD signals that immediately cleans up
- * terminated children.
+ * terminated children and adjusts the count of child processes
*/
extern "C" void sigChildHandler(int)
{
- int status = 0;
- waitpid( -1, &status, WNOHANG );
- signal(SIGCHLD, sigChildHandler);
+ while (waitpid( -1, NULL, WNOHANG) > 0)
+ {
+ if (numChildren > 0)
+ {
+ // In C++20, operator-- on variables with volateile qualifier is deprecated.
+ size_t n = numChildren - 1;
+ numChildren = n;
+ }
+ }
}
-#endif
+#endif
/* helper macro for converting stream output to a string */
#define CONVERT_TO_STRING(output, string) \
#ifdef _WIN32
cmd.addOption("--forked-child", "process is forked child, internal use only", OFCommandLine::AF_Internal);
#endif
+ cmd.addOption("--max-associations", 1, "[m]ax: integer (default: unlimited)", "limit number of parallel associations to m");
#endif
cmd.addGroup("network options:");
+ cmd.addSubGroup("IP protocol version:");
+ cmd.addOption("--ipv4", "-i4", "use IPv4 only (default)");
+ cmd.addOption("--ipv6", "-i6", "use IPv6 only");
+ cmd.addOption("--ip-auto", "-i0", "use IPv6/IPv4 dual stack");
cmd.addSubGroup("association negotiation profile from configuration file:");
cmd.addOption("--config-file", "-xf", 2, "[f]ilename, [p]rofile: string",
"use profile p from config file f");
{
opt_inetd_mode = OFTrue;
opt_forkMode = OFFalse;
+ if (cmd.findOption("--fork"))
+ {
+ app.checkConflict("--inetd", "--fork", opt_inetd_mode);
+ }
+ if (cmd.findOption("--max-associations"))
+ {
+ app.checkDependence("--max-associations", "--fork", opt_forkMode);
+ }
// duplicate stdin, which is the socket passed by inetd
int inetd_fd = dup(0);
opt_forkMode = OFFalse;
if (cmd.findOption("--fork"))
{
- app.checkConflict("--inetd", "--fork", opt_inetd_mode);
opt_forkMode = OFTrue;
}
cmd.endOptionBlock();
#ifdef _WIN32
if (cmd.findOption("--forked-child")) opt_forkedChild = OFTrue;
#endif
+ if (cmd.findOption("--max-associations"))
+ {
+ app.checkDependence("--max-associations", "--fork", opt_forkMode);
+ app.checkValue(cmd.getValueAndCheckMin(opt_maxChildren, 1));
+ }
#endif
if (opt_inetd_mode)
if (cmd.findOption("--promiscuous")) opt_promiscuous = OFTrue;
if (cmd.findOption("--uid-padding")) opt_correctUIDPadding = OFTrue;
+ // set the IP protocol version
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--ipv4")) dcmIncomingProtocolFamily.set(ASC_AF_INET);
+ if (cmd.findOption("--ipv6")) dcmIncomingProtocolFamily.set(ASC_AF_INET6);
+ if (cmd.findOption("--ip-auto")) dcmIncomingProtocolFamily.set(ASC_AF_UNSPEC);
+ cmd.endOptionBlock();
+
if (cmd.findOption("--config-file"))
{
// check conflicts with other command line options
else
{
// parent process
- if (opt_forkMode) DUL_requestForkOnTransportConnectionReceipt(argc, argv);
+ if (opt_forkMode) DUL_requestForkOnTransportConnectionReceipt(argc, argv, &processCreatedCallback);
}
#endif
#ifdef HAVE_WAITPID
// register signal handler
- signal(SIGCHLD, sigChildHandler);
+ struct sigaction sa;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ sa.sa_handler = sigChildHandler;
+ sigaction(SIGCHLD, &sa, NULL);
#endif
while (cond.good())
{
+#if defined(HAVE_WAITPID) || defined(WIN32)
+ /* if the maximum number of child processes is active,
+ * wait until at least one child terminates before
+ * continuing to accept incoming associations
+ */
+ if (numChildren == opt_maxChildren)
+ {
+ OFLOG_INFO(storescpLogger, "Maximum number of associations reached, waiting for child process to terminate");
+ while (numChildren == opt_maxChildren)
+ {
+ cleanChildren(-1, OFTrue);
+ }
+ }
+#endif
+
/* receive an association and acknowledge or reject it. If the association was */
/* acknowledged, offer corresponding services and invoke one or more if required. */
cond = acceptAssociation(net, asccfg, tlsOptions.secureConnectionRequested());
- /* remove zombie child processes */
+ /* remove zombie child processes, do not block */
cleanChildren(-1, OFFalse);
/* since storescp is usually terminated with SIGTERM or the like,
const char* transferSyntaxes[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 10
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 20
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 30
- NULL, NULL, NULL, NULL, NULL }; // +5
+ NULL, NULL, NULL, NULL, NULL, NULL }; // +6
int numTransferSyntaxes = 0;
// try to receive an association. Here we either want to use blocking or
if (cond.code() == DULC_FORKEDCHILD)
{
- // OFLOG_DEBUG(storescpLogger, DimseCondition::dump(temp_str, cond));
+ // we are the parent process in fork mode and have successfully forked a child process
+ // that will handle the association. Just clean up the association in this process.
+ // Note: in C++20, operator++ on variables with volateile qualifier is deprecated.
+ size_t n = numChildren + 1;
+ numChildren = n;
goto cleanup;
}
#if defined(HAVE_FORK) || defined(_WIN32)
if (opt_forkMode)
+ {
OFLOG_INFO(storescpLogger, "Association Received in " << (DUL_processIsForkedChild() ? "child" : "parent")
<< " process (pid: " << OFStandard::getProcessID() << ")");
+ }
else
#endif
OFLOG_INFO(storescpLogger, "Association Received");
transferSyntaxes[27] = UID_JPEGXLLosslessTransferSyntax;
transferSyntaxes[28] = UID_JPEGXLJPEGRecompressionTransferSyntax;
transferSyntaxes[29] = UID_JPEGXLTransferSyntax;
- transferSyntaxes[30] = UID_DeflatedExplicitVRLittleEndianTransferSyntax;
- transferSyntaxes[31] = UID_EncapsulatedUncompressedExplicitVRLittleEndianTransferSyntax;
+ transferSyntaxes[30] = UID_DeflatedImageFrameCompressionTransferSyntax;
+ transferSyntaxes[31] = UID_DeflatedExplicitVRLittleEndianTransferSyntax;
+ transferSyntaxes[32] = UID_EncapsulatedUncompressedExplicitVRLittleEndianTransferSyntax;
if (gLocalByteOrder == EBO_LittleEndian)
{
- transferSyntaxes[32] = UID_LittleEndianExplicitTransferSyntax;
- transferSyntaxes[33] = UID_BigEndianExplicitTransferSyntax;
- } else {
- transferSyntaxes[32] = UID_BigEndianExplicitTransferSyntax;
transferSyntaxes[33] = UID_LittleEndianExplicitTransferSyntax;
+ transferSyntaxes[34] = UID_BigEndianExplicitTransferSyntax;
+ } else {
+ transferSyntaxes[33] = UID_BigEndianExplicitTransferSyntax;
+ transferSyntaxes[34] = UID_LittleEndianExplicitTransferSyntax;
}
- transferSyntaxes[34] = UID_LittleEndianImplicitTransferSyntax;
- numTransferSyntaxes = 35;
+ transferSyntaxes[35] = UID_LittleEndianImplicitTransferSyntax;
+ numTransferSyntaxes = 36;
} else {
/* We prefer explicit transfer syntaxes.
* If we are running on a Little Endian machine we prefer
OFLOG_ERROR(storescpLogger, "cannot execute command '" << cmd << "' (fork failed)");
else if (pid > 0)
{
- /* we are the parent process */
- /* remove pending zombie child processes */
- cleanChildren(pid, opt_execSync);
+ /* we are the parent process. If we are in fork mode or
+ * in synchronous exec mode, wait for the child process to terminate
+ * and then clean up the process to avoid interference with the
+ * counter that counts the number of child process in the main process
+ */
+ cleanChildren(pid, opt_execSync || opt_forkMode);
}
else // in case we are the child process, execute the command etc.
{
#ifdef HAVE_WAITPID
static void cleanChildren(pid_t pid, OFBool synch)
#else
-static void cleanChildren(pid_t /* pid */, OFBool /* synch */)
+static void cleanChildren(pid_t /* pid */, OFBool synch)
#endif
/*
* This function removes child processes that have terminated,
*/
{
#ifdef HAVE_WAITPID
- int stat_loc;
- int child = 1;
- int options = synch ? 0 : WNOHANG;
- while (child > 0)
- {
- child = OFstatic_cast(int, waitpid(pid, &stat_loc, options));
- if (child < 0)
+ int stat_loc;
+ int child = 1;
+ int options = synch ? 0 : WNOHANG;
+ while (child > 0)
{
- if (errno != ECHILD)
+ child = OFstatic_cast(int, waitpid(pid, &stat_loc, options));
+ if (child > 0)
{
- char buf[256];
- OFLOG_WARN(storescpLogger, "wait for child failed: " << OFStandard::strerror(errno, buf, sizeof(buf)));
+ if (numChildren > 0)
+ {
+ // In C++20, operator-- on variables with volateile qualifier is deprecated.
+ size_t n = numChildren - 1;
+ numChildren = n;
+ }
+ }
+ else if (child < 0)
+ {
+ if (errno != ECHILD)
+ {
+ char buf[256];
+ OFLOG_WARN(storescpLogger, "wait for child failed: " << OFStandard::strerror(errno, buf, sizeof(buf)));
+ }
}
+ if (synch) options = 0; // break out of loop
+ }
+#elif defined(WIN32)
+ if (synch && ChildProcessEvent)
+ {
+ // block until a child process has ended
+ WaitForSingleObject(ChildProcessEvent, INFINITE);
+ }
+ OFListIterator(ChildProcessData *) first = ChildProcessList.begin();
+ OFListIterator(ChildProcessData *) last = ChildProcessList.end();
+ while (first != last)
+ {
+ if ((*first)->done)
+ {
+ // clean up wait handle
+ UnregisterWaitEx((*first)->waitHandle, INVALID_HANDLE_VALUE);
+ // close process handle
+ CloseHandle((*first)->processHandle);
+ // delete list entry
+ delete *first;
+ first = ChildProcessList.erase(first);
+ // decrease counter for child processes
+ // Note: in C++20, operator-- on variables with volateile qualifier is deprecated.
+ size_t n = numChildren - 1;
+ numChildren = n;
+ }
+ else ++first;
}
-
- if (synch) child = -1; // break out of loop
- }
#endif
}
\subsection dcmrecv_network_options network options
\verbatim
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
association negotiation profile from configuration file:
-xf --config-file [f]ilename, [p]rofile: string
\section dcmrecv_copyright COPYRIGHT
-Copyright (C) 2013-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2013-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmsend_copyright COPYRIGHT
-Copyright (C) 2011-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2011-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
association negotiation debugging:
- -pts --propose-ts [n]umber: integer (1..52)
+ -pts --propose-ts [n]umber: integer (1..53)
propose n transfer syntaxes
-ppc --propose-pc [n]umber: integer (1..128)
\section echoscu_copyright COPYRIGHT
-Copyright (C) 1994-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1994-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section findscu_copyright COPYRIGHT
-Copyright (C) 1994-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1994-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2
ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1
RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
\section getscu_copyright COPYRIGHT
-Copyright (C) 2011-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2011-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\subsection movescu_network_options network options
\verbatim
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
override matching keys:
-k --key [k]ey: gggg,eeee="str" or dictionary name="str"
silently correct space-padded UIDs
\endverbatim
+\subsection movescu_tls_options transport layer security (TLS) options
+\verbatim
+transport protocol stack:
+
+ -tls --disable-tls
+ use normal TCP/IP connection (default)
+
+ +tls --enable-tls [p]rivate key file, [c]ertificate file: string
+ use authenticated secure TLS connection
+
+private key password (only with --enable-tls):
+
+ +ps --std-passwd
+ prompt user to type password on stdin (default)
+
+ +pw --use-passwd [p]assword: string
+ use specified password
+
+ -pw --null-passwd
+ use empty string as password
+
+key and certificate file format:
+
+ -pem --pem-keys
+ read keys and certificates as PEM file (default)
+
+ -der --der-keys
+ read keys and certificates as DER file
+
+certification authority:
+
+ +cf --add-cert-file [f]ilename: string
+ add certificate file to list of certificates
+
+ +cd --add-cert-dir [d]irectory: string
+ add certificates in d to list of certificates
+
+ +crl --add-crl-file [f]ilename: string
+ add certificate revocation list file
+ (implies --enable-crl-vfy)
+
+ +crv --enable-crl-vfy
+ enable leaf CRL verification
+
+ +cra --enable-crl-all
+ enable full chain CRL verification
+
+security profile:
+
+ +ph --list-profiles
+ list supported TLS profiles and exit
+
+ +pg --profile-8996
+ BCP 195 RFC 8996 TLS Profile (default)
+
+ +pm --profile-8996-mod
+ Modified BCP 195 RFC 8996 TLS Profile
+
+ # only available if underlying TLS library supports
+ # all TLS features required for this profile
+
+ +py --profile-bcp195-nd
+ Non-downgrading BCP 195 TLS Profile (retired)
+
+ +px --profile-bcp195
+ BCP 195 TLS Profile (retired)
+
+ +pz --profile-bcp195-ex
+ Extended BCP 195 TLS Profile (retired)
+
+ +pb --profile-basic
+ Basic TLS Secure Transport Connection Profile (retired)
+
+ # only available if underlying TLS library supports 3DES
+
+ +pa --profile-aes
+ AES TLS Secure Transport Connection Profile (retired)
+
+ +pn --profile-null
+ Authenticated unencrypted communication
+ (retired, was used in IHE ATNA)
+
+ciphersuite:
+
+ +cc --list-ciphers
+ list supported TLS ciphersuites and exit
+
+ +cs --cipher [c]iphersuite name: string
+ add ciphersuite to list of negotiated suites
+
+ +dp --dhparam [f]ilename: string
+ read DH parameters for DH/DSS ciphersuites
+
+server name indication:
+
+ --no-sni
+ do not use SNI (default)
+
+ --expect-sni [s]erver name: string
+ expect requests for server name s
+
+pseudo random generator:
+
+ +rs --seed [f]ilename: string
+ seed random generator with contents of f
+
+ +ws --write-seed
+ write back modified seed (only with --seed)
+
+ +wf --write-seed-file [f]ilename: string (only with --seed)
+ write modified seed to file f
+
+peer authentication:
+
+ -rc --require-peer-cert
+ verify peer certificate, fail if absent (default)
+
+ -vc --verify-peer-cert
+ verify peer certificate if present
+
+ -ic --ignore-peer-cert
+ don't verify peer certificate
+\endverbatim
+
\subsection movescu_output_options output options
\verbatim
general:
ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3
SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4
BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
DICONDE_EddyCurrentMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.601.2
DICONDE_ThermographyImageStorage 1.2.840.10008.5.1.4.1.1.601.3
DICONDE_ThermographyMultiFrameImageStorage 1.2.840.10008.5.1.4.1.1.601.4
+DICONDE_UltrasoundWaveformStorage 1.2.840.10008.5.1.4.1.1.601.5
DRAFT_RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.1
RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.7
RTBrachyApplicationSetupDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.10
HighThroughputJPEG2000RPCLImageCompressionLoss.Tr.S. 1.2.840.10008.1.2.4.202
HighThroughputJPEG2000ImageCompressionTransferSynta. 1.2.840.10008.1.2.4.203
RLELosslessTransferSyntax 1.2.840.10008.1.2.5
+DeflatedImageFrameCompressionTransferSyntax 1.2.840.10008.1.2.8.1
\endverbatim
(*) if compiled with zlib support enabled (see \e --version output)
EXITCODE_CANNOT_CLOSE_ASSOCIATION 67
EXITCODE_CMOVE_WARNING 68
EXITCODE_CMOVE_ERROR 69
+EXITCODE_CANNOT_CREATE_TLS_LAYER 70
\endverbatim
\section movescu_environment ENVIRONMENT
\section movescu_copyright COPYRIGHT
-Copyright (C) 1994-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1994-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
--fork
fork child process for each association
+
+ --max-associations [m]ax: integer (default: unlimited)
+ limit number of parallel associations to m
\endverbatim
\subsection storescp_network_options network options
\verbatim
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
association negotiation profile from configuration file:
-xf --config-file [f]ilename [p]rofile: string
ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3
SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4
BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
DICONDE_EddyCurrentMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.601.2
DICONDE_ThermographyImageStorage 1.2.840.10008.5.1.4.1.1.601.3
DICONDE_ThermographyMultiFrameImageStorage 1.2.840.10008.5.1.4.1.1.601.4
+DICONDE_UltrasoundWaveformStorage 1.2.840.10008.5.1.4.1.1.601.5
DRAFT_RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.1
RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.7
RTBrachyApplicationSetupDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.10
HighThroughputJPEG2000RPCLImageCompressionLoss.Tr.S. 1.2.840.10008.1.2.4.202
HighThroughputJPEG2000ImageCompressionTransferSynta. 1.2.840.10008.1.2.4.203
RLELosslessTransferSyntax 1.2.840.10008.1.2.5
+DeflatedImageFrameCompressionTransferSyntax 1.2.840.10008.1.2.8.1
\endverbatim
(*) if compiled with zlib support enabled (see \e --version output)
\section storescp_copyright COPYRIGHT
-Copyright (C) 1996-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1996-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section storescu_copyright COPYRIGHT
-Copyright (C) 1996-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1996-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section termscu_copyright COPYRIGHT
-Copyright (C) 2005-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2005-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
#
-# Copyright (C) 2003-2024, OFFIS e.V.
+# Copyright (C) 2003-2025, OFFIS e.V.
# All rights reserved. See COPYRIGHT file for details.
#
# This software and supporting documentation were developed by
TransferSyntax2 = LocalEndianExplicit
TransferSyntax3 = OppositeEndianExplicit
TransferSyntax4 = LittleEndianImplicit
+#
+# The "Deflated Image Frame Compression" transfer syntax is for images.
+#
[UncompressedEncapsulatedOrZlib]
TransferSyntax1 = DeflatedLittleEndianExplicit
#
# The retired "Big Endian Explicit" transfer syntax is not accepted.
#
+# The "Deflated Image Frame Compression" transfer syntax is for images.
+#
[AnyTransferSyntax]
TransferSyntax1 = JPEGBaseline
TransferSyntax45 = JPEGXLLossless
TransferSyntax46 = JPEGXLJPEGRecompression
TransferSyntax47 = JPEGXL
-TransferSyntax48 = DeflatedLittleEndianExplicit
-TransferSyntax49 = EncapsulatedUncompressedLittleEndianExplicit
-TransferSyntax50 = LocalEndianExplicit
-TransferSyntax51 = OppositeEndianExplicit
-TransferSyntax52 = LittleEndianImplicit
+TransferSyntax48 = DeflatedImageFrameCompression
+TransferSyntax49 = DeflatedLittleEndianExplicit
+TransferSyntax50 = EncapsulatedUncompressedLittleEndianExplicit
+TransferSyntax51 = LocalEndianExplicit
+TransferSyntax52 = OppositeEndianExplicit
+TransferSyntax53 = LittleEndianImplicit
# ============================================================================
[[PresentationContexts]]
PresentationContext179 = VariableModalityLUTSoftcopyPresentationStateStorage\UncompressedOrZlib
PresentationContext180 = VisualAcuityMeasurementsStorage\UncompressedOrZlib
PresentationContext181 = VolumeRenderingVolumetricPresentationStateStorage\UncompressedOrZlib
-PresentationContext182 = WaveformAnnotationSRStorage\UncompressedOrZlib
-PresentationContext183 = XADefinedProcedureProtocolStorage\UncompressedOrZlib
-PresentationContext184 = XAPerformedProcedureProtocolStorage\UncompressedOrZlib
-PresentationContext185 = XAXRFGrayscaleSoftcopyPresentationStateStorage\UncompressedOrZlib
-PresentationContext186 = XRayRadiationDoseSRStorage\UncompressedOrZlib
+PresentationContext182 = WaveformAcquisitionPresentationStateStorage\UncompressedOrZlib
+PresentationContext183 = WaveformAnnotationSRStorage\UncompressedOrZlib
+PresentationContext184 = WaveformPresentationStateStorage\UncompressedOrZlib
+PresentationContext185 = XADefinedProcedureProtocolStorage\UncompressedOrZlib
+PresentationContext186 = XAPerformedProcedureProtocolStorage\UncompressedOrZlib
+PresentationContext187 = XAXRFGrayscaleSoftcopyPresentationStateStorage\UncompressedOrZlib
+PresentationContext188 = XRayRadiationDoseSRStorage\UncompressedOrZlib
#
# retired non-image SOP classes
#
-PresentationContext187 = RETIRED_StandaloneCurveStorage\UncompressedOrZlib
-PresentationContext188 = RETIRED_StandaloneModalityLUTStorage\UncompressedOrZlib
-PresentationContext189 = RETIRED_StandaloneOverlayStorage\UncompressedOrZlib
-PresentationContext190 = RETIRED_StandalonePETCurveStorage\UncompressedOrZlib
-PresentationContext191 = RETIRED_StandaloneVOILUTStorage\UncompressedOrZlib
-PresentationContext192 = RETIRED_StoredPrintStorage\UncompressedOrZlib
+PresentationContext189 = RETIRED_StandaloneCurveStorage\UncompressedOrZlib
+PresentationContext190 = RETIRED_StandaloneModalityLUTStorage\UncompressedOrZlib
+PresentationContext191 = RETIRED_StandaloneOverlayStorage\UncompressedOrZlib
+PresentationContext192 = RETIRED_StandalonePETCurveStorage\UncompressedOrZlib
+PresentationContext193 = RETIRED_StandaloneVOILUTStorage\UncompressedOrZlib
+PresentationContext194 = RETIRED_StoredPrintStorage\UncompressedOrZlib
#
# draft non-image SOP classes
#
-PresentationContext193 = DRAFT_RTBeamsDeliveryInstructionStorage\UncompressedOrZlib
-PresentationContext194 = DRAFT_SRAudioStorage\UncompressedOrZlib
-PresentationContext195 = DRAFT_SRComprehensiveStorage\UncompressedOrZlib
-PresentationContext196 = DRAFT_SRDetailStorage\UncompressedOrZlib
-PresentationContext197 = DRAFT_SRTextStorage\UncompressedOrZlib
-PresentationContext198 = DRAFT_WaveformStorage\UncompressedOrZlib
+PresentationContext195 = DRAFT_RTBeamsDeliveryInstructionStorage\UncompressedOrZlib
+PresentationContext196 = DRAFT_SRAudioStorage\UncompressedOrZlib
+PresentationContext197 = DRAFT_SRComprehensiveStorage\UncompressedOrZlib
+PresentationContext198 = DRAFT_SRDetailStorage\UncompressedOrZlib
+PresentationContext199 = DRAFT_SRTextStorage\UncompressedOrZlib
+PresentationContext200 = DRAFT_WaveformStorage\UncompressedOrZlib
#
# DICOS Storage
#
-PresentationContext199 = DICOS_CTImageStorage\AnyTransferSyntax
-PresentationContext200 = DICOS_DigitalXRayImageStorageForPresentation\AnyTransferSyntax
-PresentationContext201 = DICOS_DigitalXRayImageStorageForProcessing\AnyTransferSyntax
-PresentationContext202 = DICOS_2DAITStorage\AnyTransferSyntax
-PresentationContext203 = DICOS_3DAITStorage\AnyTransferSyntax
-PresentationContext204 = DICOS_QuadrupoleResonanceStorage\UncompressedOrZlib
-PresentationContext205 = DICOS_ThreatDetectionReportStorage\UncompressedOrZlib
+PresentationContext201 = DICOS_CTImageStorage\AnyTransferSyntax
+PresentationContext202 = DICOS_DigitalXRayImageStorageForPresentation\AnyTransferSyntax
+PresentationContext203 = DICOS_DigitalXRayImageStorageForProcessing\AnyTransferSyntax
+PresentationContext204 = DICOS_2DAITStorage\AnyTransferSyntax
+PresentationContext205 = DICOS_3DAITStorage\AnyTransferSyntax
+PresentationContext206 = DICOS_QuadrupoleResonanceStorage\UncompressedOrZlib
+PresentationContext207 = DICOS_ThreatDetectionReportStorage\UncompressedOrZlib
#
# DICONDE Storage
#
-PresentationContext206 = DICONDE_EddyCurrentImageStorage\AnyTransferSyntax
-PresentationContext207 = DICONDE_EddyCurrentMultiframeImageStorage\AnyTransferSyntax
-PresentationContext208 = DICONDE_ThermographyImageStorage\AnyTransferSyntax
-PresentationContext209 = DICONDE_ThermographyMultiFrameImageStorage\AnyTransferSyntax
+PresentationContext208 = DICONDE_EddyCurrentImageStorage\AnyTransferSyntax
+PresentationContext209 = DICONDE_EddyCurrentMultiframeImageStorage\AnyTransferSyntax
+PresentationContext210 = DICONDE_ThermographyImageStorage\AnyTransferSyntax
+PresentationContext211 = DICONDE_ThermographyMultiFrameImageStorage\AnyTransferSyntax
+PresentationContext212 = DICONDE_UltrasoundWaveformStorage\UncompressedOrZlib
# ----------------------------------------------------------------------------
PresentationContext171 = VariableModalityLUTSoftcopyPresentationStateStorage\UncompressedOrZlib
PresentationContext172 = VisualAcuityMeasurementsStorage\UncompressedOrZlib
PresentationContext173 = VolumeRenderingVolumetricPresentationStateStorage\UncompressedOrZlib
-PresentationContext174 = WaveformAnnotationSRStorage\UncompressedOrZlib
-PresentationContext175 = XADefinedProcedureProtocolStorage\UncompressedOrZlib
-PresentationContext176 = XAPerformedProcedureProtocolStorage\UncompressedOrZlib
-PresentationContext177 = XAXRFGrayscaleSoftcopyPresentationStateStorage\UncompressedOrZlib
-PresentationContext178 = XRayRadiationDoseSRStorage\UncompressedOrZlib
+PresentationContext174 = WaveformAcquisitionPresentationStateStorage\UncompressedOrZlib
+PresentationContext175 = WaveformAnnotationSRStorage\UncompressedOrZlib
+PresentationContext176 = WaveformPresentationStateStorage\UncompressedOrZlib
+PresentationContext177 = XADefinedProcedureProtocolStorage\UncompressedOrZlib
+PresentationContext178 = XAPerformedProcedureProtocolStorage\UncompressedOrZlib
+PresentationContext179 = XAXRFGrayscaleSoftcopyPresentationStateStorage\UncompressedOrZlib
+PresentationContext180 = XRayRadiationDoseSRStorage\UncompressedOrZlib
# ============================================================================
[[Profiles]]
#
-# Copyright (C) 2003-2024, OFFIS e.V.
+# Copyright (C) 2003-2025, OFFIS e.V.
# All rights reserved. See COPYRIGHT file for details.
#
# This software and supporting documentation were developed by
# - EncapsulatedUncompressedLittleEndianExplicit
#
# - DeflatedLittleEndianExplicit
+# - DeflatedImageFrameCompression
#
# - JPEGBaseline
# - JPEGExtended:Process2+4
# - VisualAcuityMeasurementsStorage
# - VLWholeSlideMicroscopyImageStorage
# - VolumeRenderingVolumetricPresentationStateStorage
+# - WaveformAcquisitionPresentationStateStorage
# - WaveformAnnotationSRStorage
+# - WaveformPresentationStateStorage
# - WideFieldOphthalmicPhotographyStereographicProjectionImageStorage
# - WideFieldOphthalmicPhotography3DCoordinatesImageStorage
# - XADefinedProcedureProtocolStorage
# - DICONDE_EddyCurrentMultiframeImageStorage
# - DICONDE_ThermographyImageStorage
# - DICONDE_ThermographyMultiFrameImageStorage
+# - DICONDE_UltrasoundWaveformStorage
# ============================================================================
[[Profiles]]
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
T_ASC_RejectParametersReason reason;
};
+struct DCMTK_DCMNET_EXPORT T_ASC_ImplementationIdentification
+{
+ T_ASC_ImplementationIdentification();
+
+ DIC_UI ourImplementationClassUID;
+ DIC_SH ourImplementationVersionName;
+};
struct DCMTK_DCMNET_EXPORT T_ASC_Parameters
{
ASC_createAssociationParameters(
T_ASC_Parameters ** params,
long maxReceivePDUSize,
- Sint32 tcpConnectTimeout);
+ Sint32 tcpConnectTimeout,
+ const T_ASC_ImplementationIdentification& implIdentification = T_ASC_ImplementationIdentification());
/*
* same as before, but uses value of the global dcmConnectionTimeout variable.
unsigned long *associatePDUlength=NULL,
OFBool useSecureLayer=OFFalse,
DUL_BLOCKOPTIONS block=DUL_BLOCK,
- int timeout=0);
+ int timeout=0,
+ const T_ASC_ImplementationIdentification& implIdentification = T_ASC_ImplementationIdentification());
DCMTK_DCMNET_EXPORT OFCondition
ASC_acknowledgeAssociation(
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SOCKET_H
#ifndef DCOMPAT_SYS_SOCKET_H_
#define DCOMPAT_SYS_SOCKET_H_
#endif
#endif
-#ifndef HAVE_ACCESS
-
-#ifndef R_OK
-#define R_OK 0x01
-#define W_OK 0x02
-#define X_OK 0x04
-#define F_OK 0x08
-#endif
-
-DCMTK_DCMNET_EXPORT int access(const char* path, int amode);
-#else /* HAVE_ACCESS */
-
#ifdef _WIN32
/* windows defines access but not the constants */
#ifndef R_OK
#endif /* R_OK */
#endif /* _WIN32 */
-#endif /* HAVE_ACCESS */
-
#ifdef _WIN32
#define NULL_DEVICE_NAME "nul"
#else
*/
extern DCMTK_DCMNET_EXPORT OFGlobal<size_t> dcmAssociatePDUSizeLimit; /* default: 1 MB */
+/** TCP/IP protocol family to be used for network connections
+ */
+enum T_ASC_ProtocolFamily
+{
+ /// default behaviour. Currently identical to ASC_AF_INET
+ ASC_AF_Default,
+ /// only use IPv4
+ ASC_AF_INET,
+ /// only use IPv6
+ ASC_AF_INET6,
+ /// dual-stack operation, automatically select IPv4 or IPv6
+ ASC_AF_UNSPEC
+};
+
+/** TCP/IP protocol family to be supported for incoming network
+ * connections in association acceptors.
+ */
+extern DCMTK_DCMNET_EXPORT OFGlobal<T_ASC_ProtocolFamily> dcmIncomingProtocolFamily;
+
typedef void DUL_NETWORKKEY;
typedef void DUL_ASSOCIATIONKEY;
typedef unsigned char DUL_PRESENTATIONCONTEXTID;
+typedef void (*DUL_CREATEPROCESS_CALLBACK)(void *);
/** pure virtual base class for DUL mode callbacks
*/
virtual void callback(unsigned long mode) = 0;
};
-enum T_ASC_ProtocolFamily
-{
- ASC_AF_Default,
- ASC_AF_INET,
- ASC_AF_INET6,
- ASC_AF_UNSPEC
-};
-
-
typedef struct {
char applicationContextName[DUL_LEN_NAME + 1];
char callingAPTitle[DUL_LEN_TITLE + 1];
* The content of this parameter is ignored on Posix platforms but required
* on Win32, where the child process is created with CreateProcess and the
* command line parameters have to be passed from parent to child.
+ * @param pointer to a callback function that will be called on Windows
+ * when a child process has been created using CreateProcessA().
*/
-DCMTK_DCMNET_EXPORT void DUL_requestForkOnTransportConnectionReceipt(int argc, char *argv[]);
+DCMTK_DCMNET_EXPORT void DUL_requestForkOnTransportConnectionReceipt(int argc, char *argv[], DUL_CREATEPROCESS_CALLBACK cb = NULL);
/** this function sets a flag in the association that the current process
* is the parent process after a fork() operation and that the association
/*
*
- * Copyright (C) 2009-2023, OFFIS e.V.
+ * Copyright (C) 2009-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
void setACSETimeout(const Uint32 acseTimeout);
/** Set the timeout that should be waited for connection requests.
- * Only relevant in non-blocking mode (default).
+ * Only relevant in non-blocking mode (which is not the default).
* @param timeout [in] TCP/IP connection timeout in seconds.
*/
void setConnectionTimeout(const Uint32 timeout);
/*
*
- * Copyright (C) 2012-2022, OFFIS e.V.
+ * Copyright (C) 2012-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFCondition checkAssociationProfile(const OFString &profileName,
OFString& mangledName) const;
+ /** Set association implementation identification parameters
+ * @param implIdentification [in] Implementation Class UID and Implementation Version Name
+ */
+ void setImplementationIdentification(const T_ASC_ImplementationIdentification& implIdentification);
+
+ /** Returns association implementation identification parameters
+ * @return Implementation Class UID and Implementation Version Name
+ */
+ const T_ASC_ImplementationIdentification& getImplementationIdentification() const;
+
/** Force every association request to be refused by SCP, no matter what the SCU is
* offering
* @param doRefuse [in] If OFTrue, every association is being refused. DcmSCP's default
void setACSETimeout(const Uint32 acseTimeout);
/** Set the timeout that should be waited for connection requests.
- * Only relevant in non-blocking mode (default).
+ * Only relevant in non-blocking mode (which is not the default).
* @param timeout [in] TCP/IP connection timeout in seconds.
*/
void setConnectionTimeout(const Uint32 timeout);
/// called "DEFAULT" is used.
OFString m_assocCfgProfileName;
+ /// Implementation Class UID and Implementation Version Name
+ T_ASC_ImplementationIdentification m_implIdentification;
+
/// Port on which the SCP is listening for association requests. The default port is 104.
Uint16 m_port;
/*
*
- * Copyright (C) 2012-2018, OFFIS e.V.
+ * Copyright (C) 2012-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual void exit();
+ /** Restart the worker thread */
+ virtual void rerun();
+
protected:
/** Protected constructor which is called within the friend class
* exit.
* @param result The final result of the thread.
*/
- void notifyThreadExit(DcmBaseSCPWorker* thread,
+ void notifyWorkerDone(DcmBaseSCPWorker* thread,
OFCondition result);
/** Initialize network, i.e. create an instance of T_ASC_Network and set
* @param network The T_ASC_Network pointer to create the instance
* @return EC_Normal if there were no errors during initialization.
*/
- virtual OFCondition initializeNework(T_ASC_Network** network);
+ virtual OFCondition initializeNetwork(T_ASC_Network** network);
private:
// OFList<T_ASC_Association*> m_waiting;
/// Current run mode of pool
- runmode m_runMode;
+ volatile runmode m_runMode;
+
+ /// Set m_runMode to SHUTDOWN on return from listen function
+ void finishListening();
};
/** Implementation of DICOM SCP server pool. The pool waits for incoming
}
/** Perform SCP's duties on an already accepted (TCP/IP) connection.
+ * Once done, destroy the association so the worker does not appear blocked
+ * for the next request in case of reuse.
* @param assoc The association to be run
* @return Returns EC_Normal if negotiation could take place and no
* serious network error has occurred or the given association
*/
virtual OFCondition workerListen(T_ASC_Association* const assoc)
{
- return SCP::run(assoc);
+ OFCondition result = SCP::run(assoc);
+ SCP::dropAndDestroyAssociation();
+ return result;
}
};
/*
*
- * Copyright (C) 2013, OFFIS e.V.
+ * Copyright (C) 2013-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFCondition setSharedConfig(const DcmSharedSCPConfig& config);
+protected:
+
+ /** Drops association and clears internal structures to free memory,
+ * resets internal m_assoc pointer to NULL so that isConnected()
+ * will return false after this call. Exposed from DcmSCP in order
+ * to enforce proper cleanup from derived classes.
+ */
+ virtual void dropAndDestroyAssociation();
+
private:
/** Private undefined copy constructor. Shall never be called.
/*
*
- * Copyright (C) 2008-2024, OFFIS e.V.
+ * Copyright (C) 2008-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
void setAssocConfigFileAndProfile(const OFString& filename, const OFString& profile);
+ /** Set association implementation identification parameters
+ * @param implIdentification [in] Implementation Class UID and Implementation Version Name
+ */
+ void setImplementationIdentification(const T_ASC_ImplementationIdentification& implIdentification);
+
/** Set the directory that should be used by the standard C-GET handler to store objects
* that come in with the corresponding C-STORE requests
* @param storeDir [in] The directory to store to. It is checked in handleSTORERequest()
/// Configuration file containing association parameters
OFString m_assocConfigFile;
+ /// Implementation Class UID and Implementation Version Name
+ T_ASC_ImplementationIdentification m_implIdentification;
+
/// The last DIMSE successfully sent, unresponded DIMSE request
T_DIMSE_Message* m_openDIMSERequest;
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
} T_ASC_ExtendedNegotiationItem;
+T_ASC_ImplementationIdentification::T_ASC_ImplementationIdentification()
+{
+ OFStandard::strlcpy(ourImplementationClassUID,
+ OFFIS_IMPLEMENTATION_CLASS_UID,
+ sizeof(ourImplementationClassUID));
+ OFStandard::strlcpy(ourImplementationVersionName,
+ OFFIS_DTK_IMPLEMENTATION_VERSION_NAME,
+ sizeof(ourImplementationVersionName));
+
+ if (strlen(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME) > 16)
+ {
+ DCMNET_WARN("DICOM implementation version name too long: " << OFFIS_DTK_IMPLEMENTATION_VERSION_NAME);
+ }
+}
+
+
/*
** Function Bodies
*/
OFCondition
ASC_createAssociationParameters(T_ASC_Parameters ** params,
long maxReceivePDUSize,
- Sint32 tcpConnectTimeout)
+ Sint32 tcpConnectTimeout,
+ const T_ASC_ImplementationIdentification& implIdentification)
{
-
*params = (T_ASC_Parameters *) malloc(sizeof(**params));
if (*params == NULL) return EC_MemoryExhausted;
memset((char*)*params, 0, sizeof(**params));
OFStandard::strlcpy((*params)->ourImplementationClassUID,
- OFFIS_IMPLEMENTATION_CLASS_UID,
+ implIdentification.ourImplementationClassUID,
sizeof((*params)->ourImplementationClassUID));
OFStandard::strlcpy((*params)->ourImplementationVersionName,
- OFFIS_DTK_IMPLEMENTATION_VERSION_NAME,
+ implIdentification.ourImplementationVersionName,
sizeof((*params)->ourImplementationVersionName));
- if (strlen(OFFIS_DTK_IMPLEMENTATION_VERSION_NAME) > 16)
- {
- DCMNET_WARN("DICOM implementation version name too long: " << OFFIS_DTK_IMPLEMENTATION_VERSION_NAME);
- }
-
OFStandard::strlcpy((*params)->DULparams.callingImplementationClassUID,
(*params)->ourImplementationClassUID, DICOM_UI_LENGTH + 1);
OFStandard::strlcpy((*params)->DULparams.callingImplementationVersionName,
unsigned long *associatePDUlength,
OFBool useSecureLayer,
DUL_BLOCKOPTIONS block,
- int timeout)
+ int timeout,
+ const T_ASC_ImplementationIdentification& implIdentification)
{
T_ASC_Parameters *params;
DUL_ASSOCIATIONKEY *DULassociation;
int retrieveRawPDU = 0;
if (associatePDU && associatePDUlength) retrieveRawPDU = 1;
- OFCondition cond = ASC_createAssociationParameters(¶ms, maxReceivePDUSize, dcmConnectionTimeout.get());
+ OFCondition cond = ASC_createAssociationParameters(¶ms, maxReceivePDUSize, dcmConnectionTimeout.get(), implIdentification);
if (cond.bad()) return cond;
cond = ASC_setTransportLayerType(params, useSecureLayer);
/*
*
- * Copyright (C) 1998-2024, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
OFBool DcmTransportConnection::safeSelectReadableAssociation(DcmTransportConnection *connections[], int connCount, int timeout)
{
- int numberOfRounds = timeout+1;
- if (numberOfRounds < 0) numberOfRounds = 0xFFFF; /* a long time */
-
+ double dtimeout = timeout;
OFBool found = OFFalse;
- OFBool firstRound = OFTrue;
- int timeToWait=0;
+ OFTimer tmr;
int i=0;
- while ((numberOfRounds > 0)&&(! found))
+ while ((!found) && (tmr.getDiff() < dtimeout))
{
- if (firstRound)
- {
- timeToWait = 0;
- firstRound = OFFalse;
- }
- else timeToWait = 1;
for (i=0; i<connCount; i++)
{
if (connections[i])
{
- if (connections[i]->networkDataAvailable(timeToWait))
+
+ if (connections[i]->networkDataAvailable(0))
{
i = connCount; /* break out of for loop */
found = OFTrue; /* break out of while loop */
}
- timeToWait = 0;
}
} /* for */
- if (timeToWait == 1) return OFFalse; /* all entries NULL */
- numberOfRounds--;
+ if (!found) OFStandard::milliSleep(10);
} /* while */
- /* number of rounds == 0 (timeout over), do final check */
+ /* Readable connection found or timeout reached. Do final check. */
found = OFFalse;
for (i=0; i<connCount; i++)
{
if (connections[i]->networkDataAvailable(0)) found = OFTrue; else connections[i]=NULL;
}
}
+
return found;
}
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/dcmnet/diutil.h"
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
#endif
#endif /* HAVE_FLOCK */
-#ifndef HAVE_ACCESS
-
-/*
-** The access function is OS dependent.
-*/
-
-#if defined(macintosh) || defined(_WIN32)
-int access(const char* path, int /* amode */)
-{
- int rc;
- struct stat buf;
-
- rc = stat(path, &buf);
-
- /* WARNING
- ** on the macintosh if a file is there we can do anything with it except
- ** if it is locked or on a read only filesystem. Trying to find out about
- ** that is too complicated at the moment.
- */
- return rc;
-}
-#endif
-
-#endif /* HAVE_ACCESS */
DCMTK_DCMNET_EXPORT void dcmtk_plockerr(const char *s)
{
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/dimse.h" /* always include the module header */
#include "dcmtk/dcmnet/cond.h"
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmdata/dcdatset.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcelem.h"
/*
*
- * Copyright (C) 1993-2021, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/dimse.h" /* always include the module header */
#include "dcmtk/dcmdata/dcuid.h"
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/dimse.h" /* always include the module header */
#include "dcmtk/dcmnet/cond.h"
/*
*
- * Copyright (C) 1998-2024, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/dimse.h" /* always include the module header */
#include "dcmtk/dcmnet/cond.h"
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
#include "dcmtk/ofstd/oftimer.h"
-
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/dimse.h" /* always include the module header */
#include "dcmtk/dcmnet/cond.h"
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/dimse.h" /* always include the module header */
#include "dcmtk/dcmnet/cond.h"
#ifdef WITH_ZLIB
case EXS_DeflatedLittleEndianExplicit:
#endif
+ case EXS_DeflatedImageFrameCompression:
case EXS_JPEGLSLossless:
case EXS_JPEGLSLossy:
case EXS_JPEG2000LosslessOnly:
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmnet/dimse.h" /* always include the module header */
#include "dcmtk/dcmnet/cond.h"
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
-
#include "dcmtk/ofstd/ofstd.h"
#include "dcmtk/dcmnet/diutil.h"
#include "dcmtk/dcmdata/dcdatset.h"
/*
*
- * Copyright (C) 2013-2022, OFFIS e.V.
+ * Copyright (C) 2013-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
// handle incoming C-ECHO request
status = handleECHORequest(incomingMsg->msg.CEchoRQ, presInfo.presentationContextID);
+ // TODO: need to handle invalid abstract syntax
}
else if (incomingMsg->CommandField == DIMSE_C_STORE_RQ)
{
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
/* sys/socket.h included via "dcmtk/ofstd/ofsockad.h" - needed for Ultrix */
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#include <tcpd.h> /* for hosts_ctl */
int dcmtk_hosts_access(struct request_info *req);
#endif
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for FD_CLOEXEC */
-#endif
/* declare extern "C" typedef for signal handler function pointer */
typedef void(*mySIG_TYP)(int);
OFGlobal<const char *> dcmTCPWrapperDaemonName((const char *)NULL);
OFGlobal<unsigned long> dcmEnableBackwardCompatibility(0);
OFGlobal<size_t> dcmAssociatePDUSizeLimit(0x100000);
+OFGlobal<T_ASC_ProtocolFamily> dcmIncomingProtocolFamily(ASC_AF_Default);
static int networkInitialized = 0;
#ifdef _WIN32
static char **command_argv = NULL;
static int command_argc = 0;
+static DUL_CREATEPROCESS_CALLBACK create_process_callback = NULL;
#endif
OFBool DUL_processIsForkedChild()
}
-void DUL_requestForkOnTransportConnectionReceipt(int argc, char *argv[])
+void DUL_requestForkOnTransportConnectionReceipt(int argc, char *argv[], DUL_CREATEPROCESS_CALLBACK cb)
{
shouldFork = OFTrue;
#ifdef _WIN32
command_argc = argc;
command_argv = argv;
+ create_process_callback = cb;
#else
// Work around "Unused parameters"
(void) argc;
(void) argv;
+ (void) cb;
#endif
}
struct timeval timeout_val;
socklen_t len;
int nfound, connected;
- struct sockaddr from;
+ struct sockaddr_storage from;
struct linger sockarg;
#ifdef HAVE_FORK
connected = 1;
len = sizeof(from);
- if (getpeername(sock, &from, &len))
+ if (getpeername(sock, OFreinterpret_cast(struct sockaddr*, &from), &len))
{
OFOStringStream stream;
stream << "TCP Initialization Error: " << OFStandard::getLastNetworkErrorCode().message()
len = sizeof(from);
do
{
- sock = accept((*network)->networkSpecific.TCP.listenSocket, &from, &len);
+ sock = accept((*network)->networkSpecific.TCP.listenSocket, OFreinterpret_cast(struct sockaddr*, &from), &len);
#ifdef _WIN32
} while (sock == INVALID_SOCKET && WSAGetLastError() == WSAEINTR);
if (sock == INVALID_SOCKET)
// close handles in PROCESS_INFORMATION structure
// and our local copy of the socket handle.
CloseHandle(hParentProcessHandle);
- CloseHandle(pi.hProcess);
+
+ if (create_process_callback)
+ {
+ // hand the process handle over to the callback process.
+ // The user code is now responsible for closing the handle when not needed anymore.
+ (*create_process_callback)(pi.hProcess);
+ }
+ else
+ {
+ CloseHandle(pi.hProcess);
+ }
+
CloseHandle(pi.hThread);
closesocket(sock);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) < 0)
#endif
{
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
+ OFOStringStream stream;
+ stream << "TCP Initialization Error: " << OFStandard::getLastNetworkErrorCode().message()
+ << ", setsockopt failed on socket " << sock << OFStringStream_ends;
+ OFSTRINGSTREAM_GETOFSTRING(stream, msg)
return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
}
setTCPBufferLength(sock);
#endif
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&tcpNoDelay, sizeof(tcpNoDelay)) < 0)
{
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
+ OFOStringStream stream;
+ stream << "TCP Initialization Error: " << OFStandard::getLastNetworkErrorCode().message()
+ << ", setsockopt failed on socket " << sock << OFStringStream_ends;
+ OFSTRINGSTREAM_GETOFSTRING(stream, msg)
return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
}
#ifdef DISABLE_NAGLE_ALGORITHM
#endif
}
- // create string containing numerical IP address.
+
+ // lookup string containing numerical IP address.
OFString client_dns_name;
- char client_ip_address[20];
- OFStandard::snprintf(client_ip_address, sizeof(client_ip_address), "%-d.%-d.%-d.%-d", // this code is ugly but thread safe
- ((int) from.sa_data[2]) & 0xff,
- ((int) from.sa_data[3]) & 0xff,
- ((int) from.sa_data[4]) & 0xff,
- ((int) from.sa_data[5]) & 0xff);
+ OFString client_ip_address;
+ char host[NI_MAXHOST]; // buffer for numerical IP address in text form
+ char serv[NI_MAXSERV]; // buffer for port number in text form
+ if (getnameinfo((struct sockaddr*)&from, len,
+ host, sizeof(host),
+ serv, sizeof(serv),
+ NI_NUMERICHOST | NI_NUMERICSERV) == 0)
+ {
+ client_ip_address = host;
+ }
+ else
+ {
+ client_ip_address = "unknown address";
+ }
+ // lookup hostname
if (! dcmDisableGethostbyaddr.get())
- client_dns_name = OFStandard::getHostnameByAddress(&from.sa_data[2], sizeof(struct in_addr), AF_INET);
+ {
+ struct sockaddr *saddr = OFreinterpret_cast(struct sockaddr*, &from);
+ if (saddr->sa_family == AF_INET6)
+ {
+ client_dns_name = OFStandard::getHostnameByAddress(&saddr->sa_data[6], sizeof(struct in6_addr), AF_INET6);
+ }
+ else if (saddr->sa_family == AF_INET)
+ {
+ client_dns_name = OFStandard::getHostnameByAddress(&saddr->sa_data[2], sizeof(struct in_addr), AF_INET);
+ }
+ }
if (client_dns_name.length() == 0)
{
// reverse DNS lookup disabled or host not found, use numerical address
- OFStandard::strlcpy(params->callingPresentationAddress, client_ip_address,
+ OFStandard::strlcpy(params->callingPresentationAddress, client_ip_address.c_str(),
sizeof(params->callingPresentationAddress));
- OFStandard::strlcpy((*association)->remoteNode, client_ip_address, sizeof((*association)->remoteNode));
- DCMNET_DEBUG("Association Received: " << params->callingPresentationAddress );
+ OFStandard::strlcpy((*association)->remoteNode, client_ip_address.c_str(),
+ sizeof((*association)->remoteNode));
}
else
{
+ // use either full domain name (if DUL_FULLDOMAINNAME is set) or just the hostname
char node[260];
if ((*network)->options & DUL_FULLDOMAINNAME)
OFStandard::strlcpy(node, client_dns_name.c_str(), sizeof(node));
}
OFStandard::strlcpy((*association)->remoteNode, node, sizeof((*association)->remoteNode));
OFStandard::strlcpy(params->callingPresentationAddress, node, sizeof(params->callingPresentationAddress));
- DCMNET_DEBUG("Association Received: " << params->callingPresentationAddress );
}
+ DCMNET_DEBUG("Association Received: " << params->callingPresentationAddress );
#ifdef WITH_TCPWRAPPER
const char *daemon = dcmTCPWrapperDaemonName.get();
struct request_info request;
request_init(&request, RQ_CLIENT_NAME, client_dns_name.c_str(), 0);
- request_set(&request, RQ_CLIENT_ADDR, client_ip_address, 0);
+ request_set(&request, RQ_CLIENT_ADDR, client_ip_address.c_str(), 0);
request_set(&request, RQ_USER, STRING_UNKNOWN, 0);
request_set(&request, RQ_DAEMON, daemon, 0);
((*key)->applicationFunction & DICOM_APPLICATION_ACCEPTOR) &&
(! processIsForkedChild))
{
-
- socklen_t length;
-
#ifdef _WIN32
- SOCKET sock;
+ SOCKET sock = INVALID_SOCKET;
#else
- int sock;
+ int sock = -1;
#endif
- struct sockaddr_in server;
- /* Create socket for Internet type communication */
- (*key)->networkSpecific.TCP.port = *(int *) parameter;
+ // extract port number from the generic parameter passed to this function
+ (*key)->networkSpecific.TCP.port = *(int *) parameter;
+ int port = (*key)->networkSpecific.TCP.port;
- // Create socket and prevent leakage of the open socket to processes called with exec()
- // by using SOCK_CLOEXEC (where available) or FD_CLOEXEC (POSIX.1-2008)
+ // determine which protocol family we should support
+ T_ASC_ProtocolFamily supportedFamily = dcmIncomingProtocolFamily.get();
+ int af = 0;
+ switch(supportedFamily)
+ {
+ case ASC_AF_Default:
+ af = AF_INET; // for now the default is to use IPv4 only
+ break;
+ case ASC_AF_INET:
+ af = AF_INET; // IPv4 only
+ break;
+ case ASC_AF_INET6:
+ af = AF_INET6; // IPv6 only
+ break;
+ case ASC_AF_UNSPEC:
+ af = AF_INET6; // IPv6 in dual-stack mode
+ break;
+ }
+
+ // Create socket and prevent leakage of the open socket to processes called with exec()
+ // by using SOCK_CLOEXEC (where available) or FD_CLOEXEC (POSIX.1-2008)
#ifdef SOCK_CLOEXEC
- (*key)->networkSpecific.TCP.listenSocket = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
- sock = (*key)->networkSpecific.TCP.listenSocket;
+ sock = socket(af, SOCK_STREAM | SOCK_CLOEXEC, 0);
#elif defined(FD_CLOEXEC)
- (*key)->networkSpecific.TCP.listenSocket = socket(AF_INET, SOCK_STREAM, 0);
- sock = (*key)->networkSpecific.TCP.listenSocket;
- if (sock >= 0)
- {
- int flags = fcntl(sock, F_GETFD, 0);
- fcntl(sock, F_SETFD, FD_CLOEXEC | flags);
- }
+ sock = socket(af, SOCK_STREAM, 0);
+ if (sock >= 0)
+ {
+ int flags = fcntl(sock, F_GETFD, 0);
+ fcntl(sock, F_SETFD, FD_CLOEXEC | flags);
+ }
#else
- (*key)->networkSpecific.TCP.listenSocket = socket(AF_INET, SOCK_STREAM, 0);
- sock = (*key)->networkSpecific.TCP.listenSocket;
+ sock = socket(af, SOCK_STREAM, 0);
#endif
+#ifdef _WIN32
+ if (sock == INVALID_SOCKET)
+#else
+ if (sock < 0)
+#endif
+ {
+ OFString msg = "TCP Initialization Error: ";
+ msg += OFStandard::getLastNetworkErrorCode().message();
+ return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
+ }
+
+ // store socket handle
+ (*key)->networkSpecific.TCP.listenSocket = sock;
+ // make sure that no other process is already bound to the same port.
+ // In this case we want bind() to fail.
#ifdef _WIN32
- if (sock == INVALID_SOCKET)
+ if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &reuse, sizeof(reuse)) < 0)
#else
- if (sock < 0)
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) < 0)
#endif
- {
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
- return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
- }
- reuse = 1;
+ {
#ifdef _WIN32
- if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *) &reuse, sizeof(reuse)) < 0)
+ (void) shutdown(sock, 1 /* SD_SEND */);
+ closesocket(sock);
+ (*key)->networkSpecific.TCP.listenSocket = INVALID_SOCKET;
#else
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) < 0)
+ close(sock);
+ (*key)->networkSpecific.TCP.listenSocket = -1;
#endif
- {
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
- return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
- }
+ OFString msg = "TCP Initialization Error: ";
+ msg += OFStandard::getLastNetworkErrorCode().message();
+ return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
+ }
- /* Name socket using wildcards */
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = htons(OFstatic_cast(Uint16, ((*key)->networkSpecific.TCP.port)));
- if (bind(sock, (struct sockaddr *) & server, sizeof(server)))
- {
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
- return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
- }
- /* Find out assigned port number and print it out */
- length = sizeof(server);
- if (getsockname(sock, (struct sockaddr *) &server, &length))
- {
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
- return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
- }
+ // configure the IPv6 socket either as IPv6 only or as a dual stack socket
+ // that accepts IPv4 via v4-mapped
+ if (af == AF_INET6)
+ {
+ int off = (supportedFamily == ASC_AF_UNSPEC) ? 0 : 1;
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)))
+ {
+#ifdef _WIN32
+ (void) shutdown(sock, 1 /* SD_SEND */);
+ closesocket(sock);
+ (*key)->networkSpecific.TCP.listenSocket = INVALID_SOCKET;
+#else
+ close(sock);
+ (*key)->networkSpecific.TCP.listenSocket = -1;
+#endif
+ OFString msg = "TCP Initialization Error: ";
+ msg += OFStandard::getLastNetworkErrorCode().message();
+ return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
+ }
+ }
- /* If port 0 was specified by the client, the OS has assigned an unused port. */
- if ((*key)->networkSpecific.TCP.port == 0) {
- const u_short assignedPort = ntohs(server.sin_port);
- (*key)->networkSpecific.TCP.port = assignedPort;
- *(int *) parameter = assignedPort;
- }
+ // bind the socket to the given port number
+ OFBool bind_ok = OFFalse;
+ if (af == AF_INET6) {
+ struct sockaddr_in6 server6;
+ memset(&server6, 0, sizeof(server6));
+ server6.sin6_family = AF_INET6;
+ server6.sin6_addr = in6addr_any;
+ server6.sin6_port = htons(OFstatic_cast(Uint16, port));
+ if (bind(sock, (struct sockaddr *)&server6, sizeof(server6)) == 0) bind_ok = OFTrue;
+ } else if (af == AF_INET) {
+ struct sockaddr_in server;
+ memset(&server, 0, sizeof(server));
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
+ server.sin_port = htons(OFstatic_cast(Uint16, port));
+ if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == 0) bind_ok = OFTrue;
+ }
- sockarg.l_onoff = 0;
- if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &sockarg, sizeof(sockarg)) < 0)
- {
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
- return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
- }
+ if (! bind_ok) {
+#ifdef _WIN32
+ (void) shutdown(sock, 1 /* SD_SEND */);
+ closesocket(sock);
+ (*key)->networkSpecific.TCP.listenSocket = INVALID_SOCKET;
+#else
+ close(sock);
+ (*key)->networkSpecific.TCP.listenSocket = -1;
+#endif
+ OFString msg = "TCP Initialization Error: ";
+ msg += OFStandard::getLastNetworkErrorCode().message();
+ return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
+ }
+
+ // disable linger mode, i.e. when closing the socket,
+ // do not wait until all queued messages for the socket have been
+ // successfully sent or the linger timeout has been reached.
+ sockarg.l_onoff = 0;
+ if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &sockarg, sizeof(sockarg)) < 0)
+ {
+#ifdef _WIN32
+ (void) shutdown(sock, 1 /* SD_SEND */);
+ closesocket(sock);
+ (*key)->networkSpecific.TCP.listenSocket = INVALID_SOCKET;
+#else
+ close(sock);
+ (*key)->networkSpecific.TCP.listenSocket = -1;
+#endif
+ OFString msg = "TCP Initialization Error: ";
+ msg += OFStandard::getLastNetworkErrorCode().message();
+ return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
+ }
- /* Listen on the socket */
- if (listen(sock, PRV_LISTENBACKLOG) < 0)
- {
- OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
- return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
- }
+ // listen for incoming connections, limit backlog to at most
+ // PRV_LISTENBACKLOG (i.e. 50) incoming connection request
+ if (listen(sock, PRV_LISTENBACKLOG) < 0)
+ {
+#ifdef _WIN32
+ (void) shutdown(sock, 1 /* SD_SEND */);
+ closesocket(sock);
+ (*key)->networkSpecific.TCP.listenSocket = INVALID_SOCKET;
+#else
+ close(sock);
+ (*key)->networkSpecific.TCP.listenSocket = -1;
+#endif
+ OFString msg = "TCP Initialization Error: ";
+ msg += OFStandard::getLastNetworkErrorCode().message();
+ return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
+ }
+
+ // If port 0 was specified by the caller, the OS has assigned an unused port.
+ // store this port and return it in the parameter passed to this function
+ if (port == 0)
+ {
+ if (af == AF_INET6)
+ {
+ struct sockaddr_in6 sin6; socklen_t sl = sizeof(sin6);
+ if (getsockname(sock, (struct sockaddr *)&sin6, &sl) == 0)
+ port = ntohs(sin6.sin6_port);
+ }
+ else
+ {
+ struct sockaddr_in sin; socklen_t sl = sizeof(sin);
+ if (getsockname(sock, (struct sockaddr *)&sin, &sl) == 0)
+ port = ntohs(sin.sin_port);
+ }
+ (*key)->networkSpecific.TCP.port = port;
+ *(int *) parameter = port;
+ }
}
(*key)->networkSpecific.TCP.tLayer = new DcmTransportLayer();
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
t.tv_sec = timeout;
t.tv_usec = 0;
#ifdef DCMTK_HAVE_POLL
- struct pollfd pfd[] =
+ struct pollfd pfd[] =
{
{ s, POLLIN, 0 }
};
/*
*
- * Copyright (C) 1994-2024, OFFIS e.V.
+ * Copyright (C) 1994-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were partly developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#endif
BEGIN_EXTERN_C
#ifdef HAVE_NETINET_IN_SYSTM_H
if ((*association)->connection) delete (*association)->connection;
(*association)->connection = NULL;
- char buf[256];
OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::strerror(socketError, buf, sizeof(buf));
+ msg += OFStandard::getLastNetworkErrorCode().message();
return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
}
}
{
// an error other than timeout in non-blocking mode has occurred,
// either in connect() or in select().
+ OFerror_code ec = OFStandard::getLastNetworkErrorCode();
#ifdef HAVE_WINSOCK_H
(void) shutdown(s, 1 /* SD_SEND */);
(void) closesocket(s);
(*association)->connection = NULL;
OFString msg = "TCP Initialization Error: ";
- msg += OFStandard::getLastNetworkErrorCode().message();
+ msg += ec.message();
return makeDcmnetCondition(DULC_TCPINITERROR, OF_error, msg.c_str());
} else {
// success - we've opened a TCP transport connection
if (!found)
{
char buf[256];
- OFStandard::snprintf(buf, sizeof(buf), "Unrecognized PDU type: %2x", *type);
+ OFStandard::snprintf(buf, sizeof(buf), "Unrecognized PDU type: %2.2x", *type);
return makeDcmnetCondition(DULC_UNRECOGNIZEDPDUTYPE, OF_error, buf);
}
/*
*
- * Copyright (C) 2009-2024, OFFIS e.V.
+ * Copyright (C) 2009-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFBool useSecureLayer = m_cfg->transportLayerEnabled();
// Listen to a socket for timeout seconds and wait for an association request
- OFCondition cond = ASC_receiveAssociation(network,
- &m_assoc,
- m_cfg->getMaxReceivePDULength(),
- NULL,
- NULL,
- useSecureLayer,
- m_cfg->getConnectionBlockingMode(),
- OFstatic_cast(int, timeout));
+ OFCondition cond = ASC_receiveAssociation(
+ network,
+ &m_assoc,
+ m_cfg->getMaxReceivePDULength(),
+ NULL,
+ NULL,
+ useSecureLayer,
+ m_cfg->getConnectionBlockingMode(),
+ OFstatic_cast(int, timeout),
+ m_cfg->getImplementationIdentification());
// In case of a timeout in non-blocking mode, call notifier (and return
// to main event loop later)
/*
*
- * Copyright (C) 2012-2024, OFFIS e.V.
+ * Copyright (C) 2012-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
DcmSCPConfig::DcmSCPConfig() :
m_assocConfig(),
m_assocCfgProfileName("DEFAULT"),
+ m_implIdentification(),
m_port(104),
m_aetitle("DCMTK_SCP"),
m_refuseAssociation(OFFalse),
DcmSCPConfig::DcmSCPConfig(const DcmSCPConfig &old) :
m_assocConfig(old.m_assocConfig),
m_assocCfgProfileName(old.m_assocCfgProfileName),
+ m_implIdentification(old.m_implIdentification),
m_port(old.m_port),
m_aetitle(old.m_aetitle),
m_refuseAssociation(old.m_refuseAssociation),
{
m_assocConfig = obj.m_assocConfig; // performs deep copy
m_assocCfgProfileName = obj.m_assocCfgProfileName;
+ m_implIdentification = obj.m_implIdentification;
m_port = obj.m_port;
m_aetitle = obj.m_aetitle;
m_refuseAssociation = obj.m_refuseAssociation;
}
+void DcmSCPConfig::setImplementationIdentification(const T_ASC_ImplementationIdentification& implIdentification)
+{
+ m_implIdentification = implIdentification;
+}
+
+
+const T_ASC_ImplementationIdentification& DcmSCPConfig::getImplementationIdentification() const
+{
+ return m_implIdentification;
+}
+
+
OFCondition DcmSCPConfig::addPresentationContext(const OFString &abstractSyntax,
const OFList<OFString> &xferSyntaxes,
const T_ASC_SC_ROLE role,
/*
*
- * Copyright (C) 2012-2020, OFFIS e.V.
+ * Copyright (C) 2012-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
m_workersIdle(),
m_cfg(),
m_maxWorkers(5),
- m_runMode( LISTEN )
+ m_runMode( SHUTDOWN ) // LISTEN mode will be set, once actual listening will be started.
// not implemented yet: m_workersBusyTimeout(60),
// not implemented yet: m_waiting(),
{
DcmBaseSCPPool::~DcmBaseSCPPool()
{
+ // Wait that we are in SHUTDOWN mode
+ // Let busy threads finish their work and get moved from the busy list to the idle list.
+ while (m_runMode != SHUTDOWN || DcmBaseSCPPool::numThreads(OFTrue) != 0)
+ {
+ DCMNET_DEBUG("DcmBaseSCPPool: Destructor called, waiting for runMode to become SHUTDOWN (currently " << m_runMode << ")");
+ OFStandard::forceSleep(1);
+ }
+ DCMNET_DEBUG("DcmBaseSCPPool: Destructor called, cleaning up " << m_workersIdle.size() << " idle worker threads");
+ // Now all workers must be in idle list which will be joined and deleted now.
+ // Since we are in SHUTDOWN mode, no other thread can modify the lists anymore.
+ m_criticalSection.lock();
+ size_t count = 1;
+ for (OFListIterator(DcmBaseSCPWorker*) it = m_workersIdle.begin(); it != m_workersIdle.end(); ++it)
+ {
+ DCMNET_DEBUG("DcmBaseSCPPool: Joining and deleting idle worker thread " << count << ", #" << (*it)->threadID());
+ (*it)->join();
+ delete (*it);
+ count++;
+ }
+ m_criticalSection.unlock();
+ DCMNET_DEBUG("DcmBaseSCPPool: Destructor finished");
}
// ----------------------------------------------------------------------------
/* Initialize network, i.e. create an instance of T_ASC_Network*. */
T_ASC_Network *network = NULL;
- OFCondition cond = initializeNework(&network);
+ OFCondition cond = initializeNetwork(&network);
if(cond.bad())
+ {
+ finishListening();
return cond;
+ }
/* As long as all is fine (or we have been to busy handling last connection request) keep listening */
while ( m_runMode == LISTEN && ( cond.good() || (cond == NET_EC_SCPBusy) ) )
OFBool useSecureLayer = m_cfg.transportLayerEnabled();
// Listen to a socket for timeout seconds for an association request, accepts TCP connection.
- cond = ASC_receiveAssociation( network, &assoc, m_cfg.getMaxReceivePDULength(), NULL, NULL, useSecureLayer,
- m_cfg.getConnectionBlockingMode(), OFstatic_cast(int, m_cfg.getConnectionTimeout()) );
+ cond = ASC_receiveAssociation(
+ network,
+ &assoc,
+ m_cfg.getMaxReceivePDULength(),
+ NULL,
+ NULL,
+ useSecureLayer,
+ m_cfg.getConnectionBlockingMode(),
+ OFstatic_cast(int, m_cfg.getConnectionTimeout()),
+ m_cfg.getImplementationIdentification());
/* If we have a connection request, try to find/create a worker to handle it */
if (cond.good())
cond = EC_Normal;
}
}
+ // Log why we left the listen loop
+ if (cond.bad())
+ DCMNET_DEBUG("DcmBaseSCPPool: Leaving listen loop due to error: " << cond.text());
+ else if (cond == NET_EC_SCPBusy)
+ DCMNET_DEBUG("DcmBaseSCPPool: Leaving listen loop due to too many concurrent connections (busy).");
+ else if (m_runMode == STOP)
+ DCMNET_DEBUG("DcmBaseSCPPool: Leaving listen loop due to stop request.");
+ else
+ DCMNET_DEBUG("DcmBaseSCPPool: Leaving listen loop, result: " << cond.text() << " (runMode: " << m_runMode << ")");
- m_criticalSection.lock();
- m_runMode = SHUTDOWN;
-
- // iterate over all busy workers, join their threads and delete them.
- for
- (
- OFListIterator( DcmBaseSCPPool::DcmBaseSCPWorker* ) it = m_workersBusy.begin();
- it != m_workersBusy.end();
- ++it
- )
- {
- m_criticalSection.unlock();
- (*it)->join();
- delete *it;
- m_criticalSection.lock();
- }
-
- m_workersBusy.clear();
- m_criticalSection.unlock();
+ finishListening();
/* In the end, clean up the rest of the memory and drop network */
ASC_dropNetwork(&network);
/* Try to find idle worker thread */
OFCondition result = EC_Normal;
DcmBaseSCPWorker *chosen = NULL;
+ OFBool isNewWorker = OFFalse;
/* Do we have idle worker threads that can handle the association? */
m_criticalSection.lock();
{
if (m_workersBusy.size() >= m_maxWorkers)
{
+ DCMNET_DEBUG("DcmBaseSCPPool: Maximum number of busy worker threads reached (" << m_maxWorkers << "), cannot handle incoming association");
/* No idle workers and maximum of busy workers reached? Return busy */
result = NET_EC_SCPBusy;
}
m_workersBusy.push_back(worker);
worker->setSharedConfig(sharedConfig);
chosen = worker;
+ isNewWorker = OFTrue;
+ DCMNET_DEBUG("DcmBaseSCPPool: Created new worker thread, now " << m_workersBusy.size() << " busy threads total");
}
}
}
/* Else we have idle workers, use one of them */
else
{
+ DCMNET_DEBUG("DcmBaseSCPPool: Reusing existing idle DcmSCP worker thread #" << m_workersIdle.front()->threadID());
chosen = m_workersIdle.front();
m_workersIdle.pop_front();
m_workersBusy.push_back(chosen);
result = chosen->setAssociation(assoc);
}
/* Start the thread */
- if (result.good())
+ if (isNewWorker && result.good())
{
if (chosen->start() != 0)
{
result = NET_EC_CannotStartSCPThread;
}
}
+ else if (result.good())
+ {
+ // If we reuse an existing worker thread, it might be waiting for an association.
+ // Wake it up now.
+ chosen->rerun();
+ }
/* Return to listen loop */
return result;
}
// ----------------------------------------------------------------------------
-void DcmBaseSCPPool::notifyThreadExit(DcmBaseSCPPool::DcmBaseSCPWorker* thread,
+void DcmBaseSCPPool::notifyWorkerDone(DcmBaseSCPPool::DcmBaseSCPWorker* thread,
OFCondition result)
{
m_criticalSection.lock();
- if( m_runMode != SHUTDOWN )
+ if (result.bad())
{
DCMNET_DEBUG("DcmBaseSCPPool: Worker thread #" << thread->threadID() << " exited with error: " << result.text());
- m_workersBusy.remove(thread);
- delete thread;
- thread = NULL;
}
+ else
+ {
+ DCMNET_DEBUG("DcmBaseSCPPool: Worker thread #" << thread->threadID() << " finished successfully.");
+ }
+ // Move thread from busy to idle lists
+ m_workersBusy.remove(thread);
+ m_workersIdle.push_back(thread);
+ DCMNET_DEBUG("DcmBaseSCPPool: Put worker thread #" << thread->threadID() << " back to idle list; now "
+ << m_workersBusy.size() << " busy and " << m_workersIdle.size() << " idle worker threads.");
m_criticalSection.unlock();
}
// ----------------------------------------------------------------------------
-OFCondition DcmBaseSCPPool::initializeNework(T_ASC_Network** network)
+OFCondition DcmBaseSCPPool::initializeNetwork(T_ASC_Network** network)
{
OFCondition cond = ASC_initializeNetwork(NET_ACCEPTOR, OFstatic_cast(int, m_cfg.getPort()), m_cfg.getACSETimeout(), network);
if (cond.good())
return cond;
}
+
/* *********************************************************************** */
/* DcmBaseSCPPool::BaseSCPWorker class */
/* *********************************************************************** */
DcmBaseSCPPool::DcmBaseSCPWorker::~DcmBaseSCPWorker()
{
- // do nothing
}
// ----------------------------------------------------------------------------
OFCondition DcmBaseSCPPool::DcmBaseSCPWorker::setAssociation(T_ASC_Association* assoc)
{
if (busy())
+ {
+ DCMNET_DEBUG("DcmBaseSCPPool: Worker thread #" << threadID() << " is already busy, cannot set new association");
return NET_EC_AlreadyConnected;
+ }
if ( (m_assoc != NULL) || (assoc == NULL) )
return DIMSE_ILLEGALASSOCIATION;
if(!m_assoc)
{
DCMNET_ERROR("DcmBaseSCPPool: Worker thread #" << threadID() << " received run command but has no association, exiting");
- m_pool.notifyThreadExit(this, ASC_NULLKEY);
- thread_exit();
+ m_pool.notifyWorkerDone(this, ASC_NULLKEY);
}
else
{
T_ASC_Association *param = m_assoc;
m_assoc = NULL;
result = workerListen(param);
- DCMNET_DEBUG("DcmBaseSCPPool: Worker thread #" << threadID() << " returns with code: " << result.text() );
+ m_pool.notifyWorkerDone(this, result);
+ DCMNET_DEBUG("DcmBaseSCPPool: Worker thread #" << threadID() << " finished handling association, dropping and destroying its association");
+ DCMNET_DEBUG("DcmBaseSCPPool: Worker thread #" << threadID() << " returns with result: " << result.text() );
}
- m_pool.notifyThreadExit(this, result);
- thread_exit();
return;
}
thread_exit();
}
+// ----------------------------------------------------------------------------
+
+void DcmBaseSCPPool::DcmBaseSCPWorker::rerun()
+{
+ DcmBaseSCPPool::DcmBaseSCPWorker::run();
+}
+
+// ----------------------------------------------------------------------------
+
+void DcmBaseSCPPool::finishListening()
+{
+ m_criticalSection.lock();
+ // Set run mode to SHUTDOWN which signals destructor that its time to clean up
+ m_runMode = SHUTDOWN;
+ m_criticalSection.unlock();
+}
+
+
#endif // WITH_THREADS
return EC_Normal;
}
+void DcmThreadSCP::dropAndDestroyAssociation()
+{
+ DcmSCP::dropAndDestroyAssociation();
+}
+
// ----------------------------------------------------------------------------
OFCondition DcmThreadSCP::run(T_ASC_Association* incomingAssoc)
/*
*
- * Copyright (C) 2008-2024, OFFIS e.V.
+ * Copyright (C) 2008-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
}
/* initialize association parameters, i.e. create an instance of T_ASC_Parameters*. */
- cond = ASC_createAssociationParameters(&m_params, m_maxReceivePDULength, m_tcpConnectTimeout);
+ cond = ASC_createAssociationParameters(&m_params, m_maxReceivePDULength, m_tcpConnectTimeout, m_implIdentification);
if (cond.bad())
{
DCMNET_ERROR(DimseCondition::dump(tempStr, cond));
m_assocConfigProfile = profile;
}
+void DcmSCU::setImplementationIdentification(const T_ASC_ImplementationIdentification& implIdentification)
+{
+ m_implIdentification = implIdentification;
+}
+
void DcmSCU::setStorageDir(const OFString& storeDir)
{
m_storageDir = storeDir;
/*
*
- * Copyright (C) 2013-2014, OFFIS e.V.
+ * Copyright (C) 2013-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/oftest.h"
#include "dcmtk/dcmnet/scppool.h"
#include "dcmtk/dcmnet/scu.h"
+#include "dcmtk/ofstd/ofthread.h"
+
+
+const size_t NUM_THREADS = 20;
struct TestSCU : DcmSCU, OFThread
{
- OFCondition result;
+
+ TestSCU() : m_result()
+ {
+ m_resultMutex.lock();
+ m_result = EC_IllegalCall;
+ m_resultMutex.unlock();
+ }
+
+ void getResult(OFCondition& result)
+ {
+ m_resultMutex.lock();
+ result = m_result;
+ m_resultMutex.unlock();
+ }
+
protected:
+
void run()
{
negotiateAssociation();
- result = sendECHORequest(0);
+ m_resultMutex.lock();
+ m_result = sendECHORequest(0);
+ m_resultMutex.unlock();
releaseAssociation();
}
+
+private:
+
+ OFCondition m_result;
+ OFMutex m_resultMutex;
+
};
struct TestPool : DcmSCPPool<>, OFThread
// stopAfterCurrentAssociations().
config.setConnectionTimeout(1);
- pool.setMaxThreads(20);
+ pool.setMaxThreads(NUM_THREADS);
OFList<OFString> xfers;
xfers.push_back(UID_LittleEndianExplicitTransferSyntax);
xfers.push_back(UID_LittleEndianImplicitTransferSyntax);
pool.start();
- OFVector<TestSCU*> scus(20);
+ OFVector<TestSCU*> scus(NUM_THREADS, NULL);
for (OFVector<TestSCU*>::iterator it1 = scus.begin(); it1 != scus.end(); ++it1)
{
*it1 = new TestSCU;
// "ensure" the pool is initialized before any SCU starts connecting to it. The initialization
// can take a couple of seconds on older systems, e.g. debian i368.
- OFStandard::sleep(5);
+ OFStandard::forceSleep(5);
for (OFVector<TestSCU*>::const_iterator it2 = scus.begin(); it2 != scus.end(); ++it2)
(*it2)->start();
+ // Ensure the SCUs have time to connect and send requests also on slow systems
+ OFStandard::forceSleep(5);
for (OFVector<TestSCU*>::iterator it3 = scus.begin(); it3 != scus.end(); ++it3)
{
+ OFCondition scuResult;
+ (*it3)->getResult(scuResult);
(*it3)->join();
- OFCHECK((*it3)->result.good());
delete *it3;
+ (*it3) = NULL;
+ OFCHECK(scuResult.good());
}
+ scus.clear();
+
+ // Second round to check whether thread re-use works inside the pool
+ for (OFVector<TestSCU*>::iterator it4 = scus.begin(); it4 != scus.end(); ++it4)
+ {
+ *it4 = new TestSCU;
+ (*it4)->setAETitle("PoolTestSCU");
+ (*it4)->setPeerAETitle("PoolTestSCP");
+ (*it4)->setPeerHostName("localhost");
+ (*it4)->setPeerPort(11112);
+ (*it4)->addPresentationContext(UID_VerificationSOPClass, xfers);
+ (*it4)->initNetwork();
+ }
+
+ for (OFVector<TestSCU*>::const_iterator it2 = scus.begin(); it2 != scus.end(); ++it2)
+ (*it2)->start();
+
+ for (OFVector<TestSCU*>::iterator it3 = scus.begin(); it3 != scus.end(); ++it3)
+ {
+ OFCondition scuResult;
+ (*it3)->getResult(scuResult);
+ OFCHECK(scuResult.good());
+ (*it3)->join();
+ delete *it3;
+ }
+
// Request shutdown.
pool.stopAfterCurrentAssociations();
/*
*
- * Copyright (C) 2018-2024, Open Connections GmbH
+ * Copyright (C) 2018-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
*/
virtual OFCondition write(DcmItem &dataset);
+ /** If enabled, functional group structure is checked before actual writing
+ * is performed in the write() method. Checking might be time consuming
+ * on functional groups with many frames, though disabling might result in
+ * invalid functional group structures. Disabling should only be done if the
+ * user knows that the functional groups are valid, wants to to adapt the
+ * functional groups manually after calling write() or knows what he's doing
+ * otherwise.<br>
+ * Per default, checking is enabled.
+ * @param doCheck If OFTrue, checking will be performed. If OFFalse,
+ * no checks are performed.
+ */
+ virtual void setCheckFGOnWrite(const OFBool doCheck);
+
+ /** Returns whether functional group structure is checked before actual
+ * writing is performed in the write() method.
+ * @return OFTrue if checking is performed, OFFalse otherwise
+ */
+ virtual OFBool getCheckFGOnWrite();
+
+ /** Set whether attribute values should be checked on writing, i.e. if writing
+ * should fail if attribute values violate their VR, VM, character set or value length.
+ * A missing but required value is always considered an error, independent of this setting.
+ * If set to OFFalse, writing will always succeed, even if attribute value constraints
+ * are violated. A warning instead of an error will be printed to the logger.
+ * @param doCheck If OFTrue, attribute value errors are handled as errors on writing, if OFFalse
+ * any errors are ignored.
+ */
+ virtual void setValueCheckOnWrite(const OFBool doCheck);
+
// -------------------- access ---------------------
/** Get Recognizable Visual Features
ContentIdentificationMacro m_ContentIdentification;
/// Binary frame data
- OFVector<DcmIODTypes::Frame*> m_Frames;
+ OFVector<DcmIODTypes::FrameBase*> m_Frames;
};
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
/*
*
- * Copyright (C) 2016-2024, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
{
for (Uint32 n = 0; n < numFrames; n++)
{
- DcmIODTypes::Frame* f = new DcmIODTypes::Frame;
+ DcmIODTypes::Frame<T>* f = new DcmIODTypes::Frame<T>(numBytesFrame);
if (f)
{
- f->length = numBytesFrame;
- f->pixData = new Uint8[f->length];
- memcpy(f->pixData, pixData + n*numBytesFrame/2, numBytesFrame);
+ memcpy(f->m_pixData, pixData + n*numBytesFrame/2, numBytesFrame);
map.m_Frames.push_back(f);
}
else
{
for (Uint32 n=0; n < numFrames; n++)
{
- DcmIODTypes::Frame* f = new DcmIODTypes::Frame;
- if (f)
+ DcmIODTypes::Frame<Float32>* f = new DcmIODTypes::Frame<Float32>(numBytesFrame);
+ if (f && f->m_pixData)
{
- f->length = numBytesFrame;
- f->pixData = new Uint8[f->length];
- memcpy(f->pixData, pixData + n*numBytesFrame/4, numBytesFrame);
+ memcpy(f->m_pixData, pixData + n*numBytesFrame/4, numBytesFrame);
map.m_Frames.push_back(f);
}
else
{
for (Uint16 n=0; n < numFrames; n++)
{
- DcmIODTypes::Frame* f = new DcmIODTypes::Frame;
- if (f)
+ DcmIODTypes::Frame<Float64>* f = new DcmIODTypes::Frame<Float64>(numBytesFrame);
+ if (f && f->m_pixData)
{
- f->length = numBytesFrame;
- f->pixData = new Uint8[f->length];
- memcpy(f->pixData, pixData + n*numBytesFrame/8, numBytesFrame);
+ memcpy(f->m_pixData, pixData + n*numBytesFrame/8, numBytesFrame);
map.m_Frames.push_back(f);
}
else
map.getRows(rows);
map.getColumns(cols);
const size_t numFrames = map.m_Frames.size();
- const size_t numBytesFrame = map.m_Frames[0]->length;
+ const size_t numBytesFrame = map.m_Frames[0]->getLengthInBytes();
const size_t numPixelsFrame = rows * cols;
// Creates the correct pixel data element, based on the image pixel module used.
// I.e. For integer data, the "Pixel Data" element is used, i.e. the DcmElement type
{
for (size_t f = 0; f < numFrames; ++f)
{
- memcpy(ptr, map.m_Frames[f]->pixData, numBytesFrame);
+ memcpy(ptr, map.m_Frames[f]->getPixelData(), numBytesFrame);
ptr += numPixelsFrame;
}
OFCondition result = element.put(item);
{
if (!perFrameInformation.empty())
{
- OFunique_ptr<DcmIODTypes::Frame> f(new DcmIODTypes::Frame);
+ OFunique_ptr<DcmIODTypes::Frame<PixelType> > f(new DcmIODTypes::Frame<PixelType>(numPixels * sizeof(PixelType)));
if (f)
{
- f->length = numPixels * sizeof(PixelType);
- f->pixData = new Uint8[f->length];
- memcpy(f->pixData, data, f->length);
+ memcpy(f->m_pixData, data, f->getLengthInBytes());
m_Map.m_Frames.push_back(f.release());
OFVector<FGBase*>::const_iterator fg = perFrameInformation.begin();
while ( result.good() && (fg != perFrameInformation.end()) )
{
if (frameNumber < m_Map.m_Frames.size())
{
- return (PixelType*)(m_Map.m_Frames[frameNumber]->pixData);
+ DcmIODTypes::Frame<PixelType> * f = OFstatic_cast(DcmIODTypes::Frame<PixelType>*, m_Map.m_Frames[frameNumber]);
+ if (f)
+ {
+ return f->m_pixData;
+ }
}
return NULL;
}
}
+OFBool DPMParametricMapIOD::getCheckFGOnWrite()
+{
+ return m_FGInterface.getCheckOnWrite();
+}
+
+
+void DPMParametricMapIOD::setCheckFGOnWrite(const OFBool doCheck)
+{
+ m_FGInterface.setCheckOnWrite(doCheck);
+}
+
+
+void DPMParametricMapIOD::setValueCheckOnWrite(const OFBool doCheck)
+{
+ // Forward setting into all modules
+ m_DPMParametricMapSeriesModule.setValueCheckOnWrite(doCheck);
+ m_IODEnhGeneralEquipmentModule.setValueCheckOnWrite(doCheck);
+ m_IODMultiframeDimensionModule.setValueCheckOnWrite(doCheck);
+ m_IODAcquisitionContextModule.setValueCheckOnWrite(doCheck);
+ m_IODCommonInstanceReferenceModule.setValueCheckOnWrite(doCheck);
+
+ m_IODMultiFrameFGModule.setValueCheckOnWrite(doCheck);
+ m_DPMParametricMapImageModule.setValueCheckOnWrite(doCheck);
+ m_DPMParametricMapSeriesModule.setValueCheckOnWrite(doCheck);
+ DcmIODImage::setValueCheckOnWrite(doCheck);
+}
+
+
OFCondition DPMParametricMapIOD::getColumns(Uint16& cols)
{
return getImagePixel().getColumns(cols);
# make sure executables are linked to the corresponding libraries
foreach(PROGRAM dcmp2pgm dcmprscp dcmprscu dcmpsmk dcmpschk dcmpsprt dcmpsrcv dcmpssnd)
- DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmpstat dcmdsig dcmsr dcmimage dcmimgle dcmqrdb dcmnet dcmtls dcmdata oflog ofstd)
+ DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmpstat dcmdsig dcmsr dcmimage dcmimgle dcmqrdb dcmtls)
endforeach()
foreach(PROGRAM dcmmkcrv dcmmklut)
- DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmdsig dcmsr dcmimage dcmimgle dcmdata oflog ofstd)
+ DCMTK_TARGET_LINK_MODULES(${PROGRAM} dcmdsig dcmsr dcmimage dcmimgle)
endforeach()
../include/dcmtk/dcmpstat/dvpsall.h ../include/dcmtk/dcmpstat/dvpsgal.h \
../include/dcmtk/dcmpstat/dvpscul.h ../include/dcmtk/dcmpstat/dvpsvll.h \
../include/dcmtk/dcmpstat/dvpsvwl.h ../include/dcmtk/dcmpstat/dvpsdal.h \
- ../include/dcmtk/dcmpstat/dvpssvl.h ../include/dcmtk/dcmpstat/dvpspl.h
+ ../include/dcmtk/dcmpstat/dvpssvl.h ../include/dcmtk/dcmpstat/dvpspl.h \
+ ../include/dcmtk/dcmpstat/dvpsri.h
dcmpsmk.o: dcmpsmk.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
../include/dcmtk/dcmpstat/dvpscul.h ../include/dcmtk/dcmpstat/dvpsvll.h \
../include/dcmtk/dcmpstat/dvpsvwl.h ../include/dcmtk/dcmpstat/dvpsdal.h \
../include/dcmtk/dcmpstat/dvpssvl.h ../include/dcmtk/dcmpstat/dvpspl.h \
- ../include/dcmtk/dcmpstat/dvpshlp.h
+ ../include/dcmtk/dcmpstat/dvpshlp.h ../include/dcmtk/dcmpstat/dvpsri.h
dcmpsprt.o: dcmpsprt.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/ofstream.h \
../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../include/dcmtk/dcmpstat/dvpsgal.h ../include/dcmtk/dcmpstat/dvpscul.h \
../include/dcmtk/dcmpstat/dvpsvll.h ../include/dcmtk/dcmpstat/dvpsvwl.h \
../include/dcmtk/dcmpstat/dvpsdal.h ../include/dcmtk/dcmpstat/dvpssvl.h \
- ../include/dcmtk/dcmpstat/dvpspl.h \
+ ../include/dcmtk/dcmpstat/dvpspl.h ../include/dcmtk/dcmpstat/dvpsri.h \
../../dcmtls/include/dcmtk/dcmtls/tlstrans.h \
../../dcmnet/include/dcmtk/dcmnet/dcmtrans.h \
../../dcmtls/include/dcmtk/dcmtls/tlsdefin.h \
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_RDONLY */
-#endif
END_EXTERN_C
#include "dcmtk/ofstd/ofstream.h"
unsigned short targetPort = dvi.getTargetPort(opt_printer);
OFBool targetDisableNewVRs = dvi.getTargetDisableNewVRs(opt_printer);
OFBool targetUseTLS = dvi.getTargetUseTLS(opt_printer);
+ T_ASC_ProtocolFamily targetProtocol = dvi.getTargetProtocol(opt_printer);
+ dcmIncomingProtocolFamily.set(targetProtocol);
if (targetPort == 0)
{
/*
- * Copyright (C) 1999-2024, OFFIS e.V.
+ * Copyright (C) 1999-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#ifdef HAVE_IO_H
#include <io.h>
#endif
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_RDONLY */
-#endif
END_EXTERN_C
#include "dcmtk/ofstd/ofstream.h"
#include "dcmtk/dcmdata/dctk.h" /* for class DcmDataset */
#include "dcmtk/dcmnet/dul.h"
#include "dcmtk/dcmpstat/dcmpstat.h" /* for DcmPresentationState */
+#include "dcmtk/dcmpstat/dvpsri.h" /* for dcmPresentationStateValidationMode */
#include "dcmtk/ofstd/ofstd.h"
#ifdef WITH_ZLIB
}
#define SHORTCOL 3
-#define LONGCOL 12
+#define LONGCOL 18
int main(int argc, char *argv[])
{
cmd.addOption("--version", "print version information and exit", OFCommandLine::AF_Exclusive);
OFLog::addOptions(cmd);
+ cmd.addGroup("validation options:");
+ cmd.addOption("--validate-std", "images referenced by GSPS must belong to the\nsame SOP class (default)");
+ cmd.addOption("--validate-related", "images referenced by GSPS may belong to related\n'for presentation' and 'for processing' SOP class");
+ cmd.addOption("--validate-relaxed", "images referenced by GSPS may be any SOP class");
+
/* evaluate command line */
prepareCmdLineArgs(argc, argv, OFFIS_CONSOLE_APPLICATION);
if (app.parseCommandLine(cmd, argc, argv))
}
}
+ /* validation options */
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--validate-std")) dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_standard);
+ if (cmd.findOption("--validate-related")) dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_accept_Presentation_and_Processing);
+ if (cmd.findOption("--validate-relaxed")) dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_accept_all);
+ cmd.endOptionBlock();
+
/* options */
OFLog::configureFromCommandLine(cmd, app);
}
/* print resource identifier */
OFLOG_DEBUG(dcmpschkLogger, rcsid << OFendl);
+
int paramCount = cmd.getParamCount();
for (int param=1; param <= paramCount; param++)
{
/*
*
- * Copyright (C) 1998-2022, OFFIS e.V.
+ * Copyright (C) 1998-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmnet/dul.h"
#include "dcmtk/dcmpstat/dcmpstat.h"
#include "dcmtk/dcmpstat/dvpshlp.h"
+#include "dcmtk/dcmpstat/dvpsri.h" /* for dcmPresentationStateValidationMode */
#ifdef WITH_ZLIB
#include <zlib.h> /* for zlibVersion() */
cmd.addOption("--location-media", "-lm", 2, "[f]ilesetID, fileset[UID]: string",
"image located on storage medium");
+ cmd.addGroup("validation options:", LONGCOL, SHORTCOL + 2);
+ cmd.addOption("--validate-std", "images referenced by GSPS must belong to the\nsame SOP class (default)");
+ cmd.addOption("--validate-related", "images referenced by GSPS may belong to related\n'for presentation' and 'for processing'\nSOP class");
+ cmd.addOption("--validate-relaxed", "images referenced by GSPS may be any SOP class");
+
cmd.addGroup("output options:");
cmd.addSubGroup("output transfer syntax:");
cmd.addOption("--write-xfer-same", "+t=", "write with same TS as image file (default)");
}
cmd.endOptionBlock();
+ /* validation options */
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--validate-std")) dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_standard);
+ if (cmd.findOption("--validate-related")) dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_accept_Presentation_and_Processing);
+ if (cmd.findOption("--validate-relaxed")) dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_accept_all);
+ cmd.endOptionBlock();
+
cmd.beginOptionBlock();
if (cmd.findOption("--write-xfer-same")) opt_oxfer = EXS_Unknown;
if (cmd.findOption("--write-xfer-little")) opt_oxfer = EXS_LittleEndianExplicit;
/*
*
- * Copyright (C) 1999-2024, OFFIS e.V.
+ * Copyright (C) 1999-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_RDONLY */
-#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* required for sys/stat.h */
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for stat, fstat */
-#endif
END_EXTERN_C
#include "dcmtk/dcmpstat/dvpsdef.h" /* for constants */
#include "dcmtk/dcmnet/dcmlayer.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmpstat/dcmpstat.h"
+#include "dcmtk/dcmpstat/dvpsri.h" /* for dcmPresentationStateValidationMode */
#ifdef WITH_OPENSSL
#include "dcmtk/dcmtls/tlstrans.h"
unsigned short networkPort = dvi.getTargetPort(opt_cfgID);
unsigned long networkMaxPDU = dvi.getTargetMaxPDU(opt_cfgID);
const char *networkAETitle = dvi.getTargetAETitle(opt_cfgID);
+ const char *validationMode = dvi.getTargetValidationMode(opt_cfgID);
if (networkAETitle==NULL) networkAETitle = dvi.getNetworkAETitle();
unsigned short messagePort = dvi.getMessagePort(); /* port number for IPC */
OFBool keepMessagePortOpen = dvi.getMessagePortKeepOpen();
OFBool useTLS = dvi.getTargetUseTLS(opt_cfgID);
OFBool notifyTermination = OFTrue; // notify IPC server of application termination
+ T_ASC_ProtocolFamily targetProtocol = dvi.getTargetProtocol(opt_cfgID);
+ dcmIncomingProtocolFamily.set(targetProtocol);
+
+ if (validationMode)
+ {
+ OFString vmode(validationMode);
+ if (vmode == "STD") dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_standard);
+ else if (vmode == "RELATED") dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_accept_Presentation_and_Processing);
+ else if (vmode == "RELAXED") dcmPresentationStateValidationMode.set(DVPSReferencedImage::CVM_accept_all);
+ else
+ {
+ OFLOG_WARN(dcmpsrcvLogger, "unknown validation mode '" << vmode << "', ignoring");
+ }
+ }
#ifdef WITH_OPENSSL
/* TLS directory */
/*
*
- * Copyright (C) 1999-2024, OFFIS e.V.
+ * Copyright (C) 1999-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_RDONLY */
-#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* required for sys/stat.h */
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for stat, fstat */
-#endif
END_EXTERN_C
#include "dcmtk/dcmpstat/dvpsdef.h" /* for constants */
#ifdef LOCK_IMAGE_FILES
/* shared lock image file */
#ifdef O_BINARY
- int lockfd = open(imgFile, O_RDONLY | O_BINARY, 0666);
+ int lockfd = open(imgFile, O_RDONLY | O_BINARY);
#else
- int lockfd = open(imgFile, O_RDONLY, 0666);
+ int lockfd = open(imgFile, O_RDONLY);
#endif
if (lockfd < 0)
{
\section dcmmkcrv_copyright COPYRIGHT
-Copyright (C) 1998-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1998-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmmklut_copyright COPYRIGHT
-Copyright (C) 1998-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1998-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmp2pgm_copyright COPYRIGHT
-Copyright (C) 1998-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1998-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmprscp_files FILES
-<em>\<etcdir\>/dcmpstat.cfg</em>, <em>\<etcdir\>/printers.cfg</em> - sample configuration files
+<em>\<etcdir\>/dcmpstat.cfg</em>, <em>\<etcdir\>/printers.cfg</em> - sample
+configuration files
\section dcmprscp_see_also SEE ALSO
\section dcmprscp_copyright COPYRIGHT
-Copyright (C) 1999-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1999-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmprscu_files FILES
-<em>\<etcdir\>/dcmpstat.cfg</em>, <em>\<etcdir\>/printers.cfg</em> - sample configuration files
+<em>\<etcdir\>/dcmpstat.cfg</em>, <em>\<etcdir\>/printers.cfg</em> - sample
+configuration files
\section dcmprscu_see_also SEE ALSO
\section dcmprscu_copyright COPYRIGHT
-Copyright (C) 1999-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1999-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
use config file f for the logger
\endverbatim
+\subsection dcmpschk_validation_options validation options
+\verbatim
+ --validate-std
+ images referenced by GSPS must belong to the
+ same SOP class (default)
+
+ --validate-related
+ images referenced by GSPS may belong to related
+ 'for presentation' and 'for processing' SOP class
+
+ --validate-relaxed
+ images referenced by GSPS may be any SOP class
+\endverbatim
+
\section dcmpschk_logging LOGGING
The level of logging output of the various command line tools and underlying
\section dcmpschk_copyright COPYRIGHT
-Copyright (C) 2000-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2000-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
image located on storage medium
\endverbatim
+\subsection dcmpsmk_validation_options validation options
+\verbatim
+ --validate-std
+ images referenced by GSPS must belong to the
+ same SOP class (default)
+
+ --validate-related
+ images referenced by GSPS may belong to related
+ 'for presentation' and 'for processing' SOP class
+
+ --validate-relaxed
+ images referenced by GSPS may be any SOP class
+\endverbatim
+
\subsection dcmpsmk_output_options output options
\verbatim
output transfer syntax:
\section dcmpsmk_copyright COPYRIGHT
-Copyright (C) 1998-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1998-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmpsprt_copyright COPYRIGHT
-Copyright (C) 1999-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1999-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmpsrcv_copyright COPYRIGHT
-Copyright (C) 1998-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1998-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmpssnd_copyright COPYRIGHT
-Copyright (C) 1998-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1998-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
#
-# Copyright (C) 1998-2024, OFFIS e.V.
+# Copyright (C) 1998-2025, OFFIS e.V.
# All rights reserved. See COPYRIGHT file for details.
#
# This software and supporting documentation were developed by
# than zero. Optional setting, default is Unlimited (wait for TCP/IP timeout).
# Timeout = 5
+# IP protocol family to be used. Permitted values are AF_INET (IPv4 only),
+# AF_INET6 (IPv6 only) and AF_UNSPEC (for outgoing connections, use DNS
+# lookup to determine protocol, for incoming connections use dual-stack mode).
+# Optional setting, default is AF_INET.
+Protocol = AF_INET
+
# ----------------------------------------------------------------------------
# This section contains the settings for the graphical user interface (GUI).
[GUI]
# ----------------------------------------------------------------------------
#
# IP protocol family to be used. Permitted values are AF_INET (IPv4 only),
-# AF_INET6 (IPv6 only) and AF_UNSPEC (use DNS lookup to determine protocol).
+# AF_INET6 (IPv6 only) and AF_UNSPEC (for outgoing connections, use DNS
+# lookup to determine protocol, for incoming connections use dual-stack mode).
# Optional setting, default is AF_INET.
#
# protocol = AF_INET
#
# RandomSeed = random.dat
#
+# ============================================================================
+# The next settings described below is only used with entries of type
+# RECEIVER and have no meaning for other entry types.
+# ============================================================================
+#
+# Set validation mode for incoming presentation states.
+# Default is to enforce the rule that all images referenced by one presentation
+# state must belong to the same SOP class. This can be relaxed to accept either
+# related 'for presentation' and 'for processing' SOP class references in
+# one presentation state, or to not enforce this rule at all.
+# Known terms are:
+# STD: enforce the one SOP class rule as defined in the standard
+# RELATED: permit related 'for presentation'/'for processing' SOP classes
+# RELAXED: images referenced by GSPS may be of any SOP class
+# Optional setting, default is: STD.
+#
+# ValidationMode = STD
#
# ============================================================================
# The next two settings described below are only used with entries of type
ImplicitOnly = false
DisableNewVRs = false
BitPreservingMode = false
+ValidationMode = STD
# ----------------------------------------------------------------------------
[RECEIVE_2]
PeerAuthentication = REQUIRE
Certificate = sitecert.pem
PrivateKey = sitekey.pem
+ValidationMode = STD
# ----------------------------------------------------------------------------
# Print SCP that supports most options of the DICOM Print protocol and
/*
*
- * Copyright (C) 1998-2022, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/*
*
- * Copyright (C) 1998-2024, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
OFBool getTargetBitPreservingMode(const char *targetID);
+ /** returns the VALIDATIONMODE entry for the storage peer with the given
+ * target ID from the configuration file.
+ * @param targetID communication target ID, must be one of the target
+ * identifiers returned by getTargetID().
+ * @return entry if present in the config file, NULL otherwise.
+ */
+ const char *getTargetValidationMode(const char *targetID);
+
/** returns the CORRECTUIDPADDING entry for the storage peer with the given
* target ID from the configuration file.
* @param targetID communication target ID, must be one of the target
*/
OFBool getTargetPrinterSupportsAnnotationBoxSOPClass(const char *targetID);
- /** returns OFTrue if an SESSIONLABELANNOTATION entry for the printer
+ /** returns OFTrue if an SESSIONLABELANNOTATION entry for the printer
* with the given target ID from the configuration file exists and is true.
* @param targetID communication target ID, must be one of the target
* identifiers returned by getTargetID() for peer type DVPSE_printerAny.
* @return value if present, NULL otherwise.
*/
const char *getTargetPrinterAnnotationDisplayFormatID(const char *targetID, OFString& value);
-
+
/** returns the first value from the ANNOTATION entry for the printer
* with the given target ID from the configuration file.
* @param targetID communication target ID, must be one of the target
* @return value if present, 0 otherwise.
*/
Uint16 getTargetPrinterAnnotationPosition(const char *targetID);
-
+
/** returns the number of distinct values (separated by backslash characters)
* in the FILMSIZEID entry for the printer with the given
* target ID from the configuration file.
*/
OFLogger::LogLevel getLogLevel();
- /** returns the port on which the GUI application accepts notification
+ /** returns the port on which the GUI application accepts notification
* messages from the network processes.
* Value is taken from the section GENERAL/APPLICATION/MESSAGEPORT
* in the config file.
*/
unsigned long getQueryRetrieveMaxAssociations();
+ /** returns the protocol family to be supported by the Query/Retrieve SCP
+ * as configured in section GENERAL/QUERY_RETRIEVE/PROTOCOL in the config file.
+ * @return send application path name or NULL if absent.
+ */
+ T_ASC_ProtocolFamily getQueryRetrieveProtocolFamily();
+
/** returns the database folder to be used for sending/receiving/browsing.
* Value is taken from the section GENERAL/DATABASE/DIRECTORY
* in the config file. If absent, a default value is returned.
double getVOIPresetWindowWidth(const char *modality, Uint32 idx);
/* TLS settings */
-
- /** returns the directory in which TLS related files (certificates, keys,
- * random data, Diffie-Hellman parameters etc.) are located.
+
+ /** returns the directory in which TLS related files (certificates, keys,
+ * random data, Diffie-Hellman parameters etc.) are located.
* @return TLS directory path, NULL if absent.
*/
const char *getTLSFolder();
- /** returns the directory in which certificates of the trusted
- * Certification Authorities are located.
+ /** returns the directory in which certificates of the trusted
+ * Certification Authorities are located.
* @return TLS CA Certificate directory path, NULL if absent.
*/
const char *getTLSCACertificateFolder();
/** returns the file format used for certificates, keys and Diffie-Hellman
* parameters. OFTrue for PEM ("privacy enhanced mail") format, OFFalse for
- * DER ("distinguished encoding rules") format.
+ * DER ("distinguished encoding rules") format.
* @return OFTrue for PEM (default), OFFalse for DER.
*/
OFBool getTLSPEMFormat();
/* User login settings */
/** returns the directory in which user certificates and keys
- * are located.
+ * are located.
* @return User key/certificate directory path, NULL if absent.
*/
const char *getUserCertificateFolder();
*/
const char *getUserLogin(const char *userID);
- /** returns the human readable name for the given user.
+ /** returns the human readable name for the given user.
* If absent in the config file, returns NULL.
* @param userID user ID as returned by getUserID()
* @return name for the given user
/*
*
- * Copyright (C) 1998-2012, OFFIS e.V.
+ * Copyright (C) 1998-2024, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
class DCMTK_DCMPSTAT_EXPORT DVPSReferencedImage
{
+public:
+ /** SOPClassUID Validation Mode
+ */
+ enum E_ClassValidationMode
+ {
+ /** enforce the rule specified in DICOM Part 3, C.11.11,
+ * that the referenced SOP class must be same for all images
+ * referenced by a presentation state.
+ */
+ CVM_standard,
+
+ /** somewhat relax the rule that the referenced SOP class must
+ * be same for all images referenced by a presentation state
+ * by permitting instances of related "for presentation" and
+ * "for processing" SOP classes to be referenced from one
+ * presentation state.
+ */
+
+ CVM_accept_Presentation_and_Processing,
+
+ /** ignore the rule that the referenced SOP class must
+ * be same for all images referenced by a presentation state
+ */
+ CVM_accept_all
+ };
+
public:
/// default constructor
DVPSReferencedImage();
};
+/** This flag defines the validation mode applied when reading presentation
+ * states. See definition of enum E_ClassValidationMode for details.
+ * The default is CVM_standard.
+ */
+extern DCMTK_DCMPSTAT_EXPORT OFGlobal<DVPSReferencedImage::E_ClassValidationMode> dcmPresentationStateValidationMode;
+
#endif
../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../include/dcmtk/dcmpstat/dvpsibl.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/diutils.h \
../../dcmimgle/include/dcmtk/dcmimgle/didefine.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
../../dcmdata/include/dcmtk/dcmdata/dcvruc.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
../../dcmdata/include/dcmtk/dcmdata/dcpixel.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpobw.h \
../../dcmdata/include/dcmtk/dcmdata/dcovlay.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
- ../include/dcmtk/dcmpstat/dvpsdef.h
+ ../include/dcmtk/dcmpstat/dvpsdef.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h
dvpsril.o: dvpsril.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmpstat/dvpsril.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
/*
*
- * Copyright (C) 1998-2024, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmqrdb/dcmqrdbs.h" /* for DcmQueryRetrieveDatabaseStatus */
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* for fork */
-#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for waitpid */
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h> /* for wait3 */
#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for stat, fstat */
-#endif
#ifdef HAVE_SYS_UTIME_H
#include <sys/utime.h> /* for utime */
#endif
if (configPath.empty()) return EC_IllegalCall;
OFString config_filename = getQueryRetrieveServerName();
+ T_ASC_ProtocolFamily family = getQueryRetrieveProtocolFamily();
config_filename += ".cfg";
if (getQueryRetrieveAutoCreateConfigFile())
createQueryRetrieveServerConfigFile(config_filename.c_str());
DVPSHelper::cleanChildren(); // clean up old child processes before creating new ones
Sint32 timeout = getQueryRetrieveTimeout();
+ const char *family_param = "";
+ switch (family)
+ {
+ case ASC_AF_INET:
+ case ASC_AF_Default:
+ family_param = "--ipv4";
+ break;
+ case ASC_AF_INET6:
+ family_param = "--ipv6";
+ break;
+ case ASC_AF_UNSPEC:
+ family_param = "--ip-auto";
+ break;
+ }
#ifdef HAVE_FORK
// Unix version - call fork() and execl()
{
char str_timeout[20];
OFStandard::snprintf(str_timeout, sizeof(str_timeout), "%lu", OFstatic_cast(unsigned long, timeout));
- execl(server_application, server_application, "-c", config_filename.c_str(), "--allow-shutdown",
- "--timeout", str_timeout, OFreinterpret_cast(char *, 0));
+ execl(server_application, server_application, "-c", config_filename.c_str(), family_param, "--allow-shutdown", "--timeout", str_timeout, OFreinterpret_cast(char *, 0));
}
else
{
- execl(server_application, server_application, "-c", config_filename.c_str(), "--allow-shutdown", OFreinterpret_cast(char *, 0));
+ execl(server_application, server_application, "-c", config_filename.c_str(), family_param, "--allow-shutdown", OFreinterpret_cast(char *, 0));
}
DCMPSTAT_ERROR("Unable to execute '" << server_application << "'");
if (timeout > 0)
{
- OFStandard::snprintf(commandline, sizeof(commandline), "%s -c %s --allow-shutdown --timeout %lu",
- server_application, config_filename.c_str(), (unsigned long) timeout);
+ OFStandard::snprintf(commandline, sizeof(commandline), "%s -c %s %s --allow-shutdown --timeout %lu",
+ server_application, config_filename.c_str(), family_param, (unsigned long) timeout);
}
else
{
- OFStandard::snprintf(commandline, sizeof(commandline), "%s -c %s --allow-shutdown", server_application, config_filename.c_str());
+ OFStandard::snprintf(commandline, sizeof(commandline), "%s -c %s %s --allow-shutdown", server_application, config_filename.c_str(), family_param);
}
#ifdef DEBUG
/*
*
- * Copyright (C) 1998-2024, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#define L0_DESCRIPTION "DESCRIPTION"
#define L0_DETAILEDLOG "DETAILEDLOG"
#define L0_DICOMNAME "DICOMNAME"
-#define L0_DIFFIEHELLMANPARAMETERS "DIFFIEHELLMANPARAMETERS"
+#define L0_DIFFIEHELLMANPARAMETERS "DIFFIEHELLMANPARAMETERS"
#define L0_DIRECTORY "DIRECTORY"
#define L0_DISABLENEWVRS "DISABLENEWVRS"
#define L0_DISPLAYFORMAT "DISPLAYFORMAT"
#define L0_USEPEMFORMAT "USEPEMFORMAT"
#define L0_USERKEYDIRECTORY "USERKEYDIRECTORY"
#define L0_USETLS "USETLS"
+#define L0_VALIDATIONMODE "VALIDATIONMODE"
#define L0_WIDTH "WIDTH"
#define L1_APPLICATION "APPLICATION"
#define L1_DATABASE "DATABASE"
return _strnicmp(str1, str2, len);
#else
return strncasecmp(str1, str2, len);
-#endif
+#endif
}
return result;
}
+T_ASC_ProtocolFamily DVConfiguration::getQueryRetrieveProtocolFamily()
+{
+ const char *c = getConfigEntry(L2_GENERAL, L1_QUERY_RETRIEVE, L0_PROTOCOL);
+ T_ASC_ProtocolFamily result = ASC_AF_Default;
+ if (c)
+ {
+ if (strCompare(c, "AF_INET6", 8) == 0) result = ASC_AF_INET6;
+ else if (strCompare(c, "AF_INET", 7) == 0) result = ASC_AF_INET;
+ else if (strCompare(c, "AF_UNSPEC", 9) == 0) result = ASC_AF_UNSPEC;
+ }
+ return result;
+}
+
const char *DVConfiguration::getDatabaseFolder()
{
const char *result = getConfigEntry(L2_GENERAL, L1_DATABASE, L0_DIRECTORY);
copyValue(getConfigEntry(L2_COMMUNICATION, targetID, L0_ANNOTATION), 1, value);
if (value.length()) return value.c_str(); else return NULL;
}
-
+
Uint16 DVConfiguration::getTargetPrinterAnnotationPosition(const char *targetID)
{
OFString value;
return getConfigBoolEntry(L2_GENERAL, L1_TLS, L0_USEPEMFORMAT, OFTrue);
}
+const char *DVConfiguration::getTargetValidationMode(const char *targetID)
+{
+ return getConfigEntry(L2_COMMUNICATION, targetID, L0_VALIDATIONMODE);
+}
+
OFBool DVConfiguration::getTargetBitPreservingMode(const char *targetID)
{
return getConfigBoolEntry(L2_COMMUNICATION, targetID, L0_BITPRESERVINGMODE, OFFalse);
/*
*
- * Copyright (C) 1998-2024, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmdata/dctk.h"
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* for fork */
-#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for waitpid */
#endif
{
if (connection) return; // connection already open
+ OFSockAddr server;
+ OFStandard::getAddressByHostname("localhost", AF_INET, server);
+ if (server.size() == 0) return;
+
#ifdef _WIN32
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET) return;
int s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) return;
#endif
- OFSockAddr server;
- OFStandard::getAddressByHostname("localhost", AF_INET, server);
+
server.setPort(OFstatic_cast(unsigned short, htons(OFstatic_cast(unsigned short, port))));
if (connect(s, server.getSockaddr(), server.size()) < 0)
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcitem.h"
#include "dcmtk/dcmpstat/dvpsdef.h" /* for constants and macros */
+#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/ofstd/ofstd.h"
+OFGlobal<DVPSReferencedImage::E_ClassValidationMode> dcmPresentationStateValidationMode(DVPSReferencedImage::CVM_standard);
+
/* --------------- class DVPSReferencedImage --------------- */
+
DVPSReferencedImage::DVPSReferencedImage()
: referencedSOPClassUID(DCM_ReferencedSOPClassUID)
, referencedSOPInstanceUID(DCM_ReferencedSOPInstanceUID)
DcmStack stack;
flushCache();
-
+
READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, referencedSOPClassUID)
READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, referencedSOPInstanceUID)
READ_FROM_DATASET(DcmIntegerString, EVR_IS, referencedFrameNumber)
-
+
/* Now perform basic sanity checks */
if (referencedSOPClassUID.getLength() == 0)
{
OFCondition result = EC_Normal;
DcmElement *delem=NULL;
-
+
ADD_TO_DATASET(DcmUniqueIdentifier, referencedSOPClassUID)
ADD_TO_DATASET(DcmUniqueIdentifier, referencedSOPInstanceUID)
if (referencedFrameNumber.getLength() >0) { ADD_TO_DATASET(DcmIntegerString, referencedFrameNumber) }
OFBool DVPSReferencedImage::validateSOPClassUID(OFString& sopclassuid)
{
- OFBool result = OFTrue;
+ E_ClassValidationMode classValidationMode = dcmPresentationStateValidationMode.get();
if (sopclassuid.empty()) referencedSOPClassUID.getOFString(sopclassuid, 0);
- else
+ else
{
OFString currentUID;
referencedSOPClassUID.getOFString(currentUID, 0);
- if (currentUID != sopclassuid)
+ switch (classValidationMode)
{
- result = OFFalse;
- DCMPSTAT_WARN("images of different SOP classes referenced in presentation state");
+ // we accept all combinations of SOP classes
+ case CVM_accept_all:
+ if (currentUID != sopclassuid)
+ {
+ DCMPSTAT_INFO("images of different SOP classes referenced in presentation state");
+ }
+ return OFTrue;
+ /* break; */
+
+ // we accept only related SOP classes
+ case CVM_accept_Presentation_and_Processing:
+ if (currentUID != sopclassuid)
+ {
+ if ( ( sopclassuid == UID_BreastProjectionXRayImageStorageForPresentation && currentUID == UID_BreastProjectionXRayImageStorageForProcessing )
+ || ( sopclassuid == UID_BreastProjectionXRayImageStorageForProcessing && currentUID == UID_BreastProjectionXRayImageStorageForPresentation )
+ || ( sopclassuid == UID_DigitalIntraOralXRayImageStorageForPresentation && currentUID == UID_DigitalIntraOralXRayImageStorageForProcessing )
+ || ( sopclassuid == UID_DigitalIntraOralXRayImageStorageForProcessing && currentUID == UID_DigitalIntraOralXRayImageStorageForPresentation )
+ || ( sopclassuid == UID_DigitalMammographyXRayImageStorageForPresentation && currentUID == UID_DigitalMammographyXRayImageStorageForProcessing )
+ || ( sopclassuid == UID_DigitalMammographyXRayImageStorageForProcessing && currentUID == UID_DigitalMammographyXRayImageStorageForPresentation )
+ || ( sopclassuid == UID_DigitalXRayImageStorageForPresentation && currentUID == UID_DigitalXRayImageStorageForProcessing )
+ || ( sopclassuid == UID_DigitalXRayImageStorageForProcessing && currentUID == UID_DigitalXRayImageStorageForPresentation )
+ || ( sopclassuid == UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation && currentUID == UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing )
+ || ( sopclassuid == UID_IntravascularOpticalCoherenceTomographyImageStorageForProcessing && currentUID == UID_IntravascularOpticalCoherenceTomographyImageStorageForPresentation )
+ || ( sopclassuid == UID_DICOS_DigitalXRayImageStorageForPresentation && currentUID == UID_DICOS_DigitalXRayImageStorageForProcessing )
+ || ( sopclassuid == UID_DICOS_DigitalXRayImageStorageForProcessing && currentUID == UID_DICOS_DigitalXRayImageStorageForPresentation ) )
+ {
+ DCMPSTAT_INFO("images of different (but related) SOP classes referenced in presentation state");
+ return OFTrue;
+ }
+ else
+ {
+ DCMPSTAT_WARN("images of different SOP classes referenced in presentation state");
+ return OFFalse;
+ }
+ }
+ return OFTrue;
+ /* break; */
+
+ // we accept only the same SOP classes, as required by the DICOM standard
+ case CVM_standard:
+ if (currentUID != sopclassuid)
+ {
+ DCMPSTAT_WARN("images of different SOP classes referenced in presentation state");
+ return OFFalse;
+ }
+ else return OFTrue;
+ /* break; */
}
}
- return result;
+ return OFTrue;
}
void DVPSReferencedImage::setSOPClassUID(const char *uid)
OFCondition DVPSReferencedImage::getImageReference(
OFString& sopclassUID,
- OFString& instanceUID,
+ OFString& instanceUID,
OFString& frames)
{
OFCondition result = referencedSOPClassUID.getOFString(sopclassUID,0);
{
val = (Sint32) frame;
for (i=0; i<frameCacheEntries; i++) if (val == frameCache[i]) return OFTrue;
- return OFFalse;
+ return OFFalse;
}
return OFTrue; // referencedFrameNumber seems to contain garbage.
}
unsigned long i;
char str[20];
OFString aString;
-
+
updateCache();
referencedFrameNumber.clear();
if (frameCache)
{
- for (i=0; i<frameCacheEntries; i++)
+ for (i=0; i<frameCacheEntries; i++)
{
- if (frameCache[i] != (Sint32)frame)
+ if (frameCache[i] != (Sint32)frame)
{
if (aString.size() ==0) OFStandard::snprintf(str, sizeof(str), "%ld", (long)(frameCache[i]));
else OFStandard::snprintf(str, sizeof(str), "\\%ld", (long)(frameCache[i]));
}
}
} else {
- for (i=1; i<=numberOfFrames; i++)
+ for (i=1; i<=numberOfFrames; i++)
{
if (i != frame)
{
DCMTK_ADD_TEST_EXECUTABLE(msgserv msgserv.cc)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(msgserv dcmpstat dcmdsig dcmsr dcmimage dcmimgle dcmqrdb dcmnet dcmtls dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(msgserv dcmpstat dcmdsig dcmsr dcmimage)
/*
*
- * Copyright (C) 2000-2024 OFFIS e.V.
+ * Copyright (C) 2000-2025 OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#endif
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* we have to include this before sys/time.h on Solaris */
-#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h> /* for struct timeval on Linux */
#endif
/*
*
- * Copyright (C) 1993-2024, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#endif
OFCommandLine cmd;
-
cmd.setParamColumn(LONGCOL + SHORTCOL + 4);
cmd.addParam("port", "tcp/ip port number to listen on\n(default: in config file)", OFCmdParam::PM_Optional);
#endif
cmd.addGroup("network options:");
+ cmd.addSubGroup("IP protocol version:");
+ cmd.addOption("--ipv4", "-i4", "use IPv4 only (default)");
+ cmd.addOption("--ipv6", "-i6", "use IPv6 only");
+ cmd.addOption("--ip-auto", "-i0", "use IPv6/IPv4 dual stack");
+
cmd.addSubGroup("association negotiation profiles from configuration file:");
cmd.addOption("--assoc-config-file", "-xf", 3, "[f]ilename, [i]n-prof, [o]ut-prof: string",
"use profile i from f for incoming,\nand profile o from f for outgoing associations");
if (cmd.findOption("--ignore")) options.ignoreStoreData_ = OFTrue;
if (cmd.findOption("--uid-padding")) options.correctUIDPadding_ = OFTrue;
+ // set the IP protocol version
+ cmd.beginOptionBlock();
+ if (cmd.findOption("--ipv4")) dcmIncomingProtocolFamily.set(ASC_AF_INET);
+ if (cmd.findOption("--ipv6")) dcmIncomingProtocolFamily.set(ASC_AF_INET6);
+ if (cmd.findOption("--ip-auto")) dcmIncomingProtocolFamily.set(ASC_AF_UNSPEC);
+ cmd.endOptionBlock();
+
if (cmd.findOption("--assoc-config-file"))
{
// check conflicts with other command line options
// evaluate (most of) the TLS command line options (if we are compiling with OpenSSL)
tlsOptions.parseArguments(app, cmd);
+ options.secureConnectionRequested_ = tlsOptions.secureConnectionRequested();
}
/* print resource identifier */
\section dcmqridx_copyright COPYRIGHT
-Copyright (C) 1993-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1993-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\subsection dcmqrscp_network_options network options
\verbatim
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
association negotiation profiles from configuration file:
-xf --assoc-config-file
ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3
SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4
BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
DICONDE_EddyCurrentMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.601.2
DICONDE_ThermographyImageStorage 1.2.840.10008.5.1.4.1.1.601.3
DICONDE_ThermographyMultiFrameImageStorage 1.2.840.10008.5.1.4.1.1.601.4
+DICONDE_UltrasoundWaveformStorage 1.2.840.10008.5.1.4.1.1.601.5
DRAFT_RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.1
RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.7
RTBrachyApplicationSetupDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.10
(0010,0040) PatientSex
(0010,1000) OtherPatientIDs (retired)
(0010,1001) OtherPatientNames
-(0010,2160) EthnicGroup
+(0010,2160) EthnicGroup (retired)
(0010,4000) PatientComments
\endverbatim
(0010,21B0) AdditionalPatientHistory
(0020,000D) StudyInstanceUID
(0020,0010) StudyID
-(0020,1070) RETIRED_OtherStudyNumbers
+(0020,1070) OtherStudyNumbers (retired)
\endverbatim
Query/Retrieve Level: SERIES
\section dcmqrscp_copyright COPYRIGHT
-Copyright (C) 1993-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1993-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
\section dcmqrti_copyright COPYRIGHT
-Copyright (C) 1993-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1993-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
#
-# Copyright (C) 2017-2024, OFFIS e.V.
+# Copyright (C) 2017-2025, OFFIS e.V.
# All rights reserved. See COPYRIGHT file for details.
#
# This software and supporting documentation were developed by
TransferSyntax2 = LocalEndianExplicit
TransferSyntax3 = OppositeEndianExplicit
TransferSyntax4 = LittleEndianImplicit
+#
+# The "Deflated Image Frame Compression" transfer syntax is for images.
+#
[UncompressedEncapsulatedOrZlib]
TransferSyntax1 = DeflatedLittleEndianExplicit
#
# The retired "Big Endian Explicit" transfer syntax is not accepted.
#
+# The "Deflated Image Frame Compression" transfer syntax is for images.
+#
[JPEGBaseline]
TransferSyntax1 = JPEGBaseline
TransferSyntax45 = JPEGXLLossless
TransferSyntax46 = JPEGXLJPEGRecompression
TransferSyntax47 = JPEGXL
-TransferSyntax48 = DeflatedLittleEndianExplicit
-TransferSyntax49 = EncapsulatedUncompressedLittleEndianExplicit
-TransferSyntax50 = LocalEndianExplicit
-TransferSyntax51 = OppositeEndianExplicit
-TransferSyntax52 = LittleEndianImplicit
+TransferSyntax48 = DeflatedImageFrameCompression
+TransferSyntax49 = DeflatedLittleEndianExplicit
+TransferSyntax50 = EncapsulatedUncompressedLittleEndianExplicit
+TransferSyntax51 = LocalEndianExplicit
+TransferSyntax52 = OppositeEndianExplicit
+TransferSyntax53 = LittleEndianImplicit
# ============================================================================
[[PresentationContexts]]
PresentationContext179 = VariableModalityLUTSoftcopyPresentationStateStorage\UncompressedOrZlib
PresentationContext180 = VisualAcuityMeasurementsStorage\UncompressedOrZlib
PresentationContext181 = VolumeRenderingVolumetricPresentationStateStorage\UncompressedOrZlib
-PresentationContext182 = WaveformAnnotationSRStorage\UncompressedOrZlib
-PresentationContext183 = XADefinedProcedureProtocolStorage\UncompressedOrZlib
-PresentationContext184 = XAPerformedProcedureProtocolStorage\UncompressedOrZlib
-PresentationContext185 = XAXRFGrayscaleSoftcopyPresentationStateStorage\UncompressedOrZlib
-PresentationContext186 = XRayRadiationDoseSRStorage\UncompressedOrZlib
+PresentationContext182 = WaveformAcquisitionPresentationStateStorage\UncompressedOrZlib
+PresentationContext183 = WaveformAnnotationSRStorage\UncompressedOrZlib
+PresentationContext184 = WaveformPresentationStateStorage\UncompressedOrZlib
+PresentationContext185 = XADefinedProcedureProtocolStorage\UncompressedOrZlib
+PresentationContext186 = XAPerformedProcedureProtocolStorage\UncompressedOrZlib
+PresentationContext187 = XAXRFGrayscaleSoftcopyPresentationStateStorage\UncompressedOrZlib
+PresentationContext188 = XRayRadiationDoseSRStorage\UncompressedOrZlib
#
# retired non-image SOP classes
#
-PresentationContext187 = RETIRED_StandaloneCurveStorage\UncompressedOrZlib
-PresentationContext188 = RETIRED_StandaloneModalityLUTStorage\UncompressedOrZlib
-PresentationContext189 = RETIRED_StandaloneOverlayStorage\UncompressedOrZlib
-PresentationContext190 = RETIRED_StandalonePETCurveStorage\UncompressedOrZlib
-PresentationContext191 = RETIRED_StandaloneVOILUTStorage\UncompressedOrZlib
-PresentationContext192 = RETIRED_StoredPrintStorage\UncompressedOrZlib
+PresentationContext189 = RETIRED_StandaloneCurveStorage\UncompressedOrZlib
+PresentationContext190 = RETIRED_StandaloneModalityLUTStorage\UncompressedOrZlib
+PresentationContext191 = RETIRED_StandaloneOverlayStorage\UncompressedOrZlib
+PresentationContext192 = RETIRED_StandalonePETCurveStorage\UncompressedOrZlib
+PresentationContext193 = RETIRED_StandaloneVOILUTStorage\UncompressedOrZlib
+PresentationContext194 = RETIRED_StoredPrintStorage\UncompressedOrZlib
#
# draft non-image SOP classes
#
-PresentationContext193 = DRAFT_RTBeamsDeliveryInstructionStorage\UncompressedOrZlib
-PresentationContext194 = DRAFT_SRAudioStorage\UncompressedOrZlib
-PresentationContext195 = DRAFT_SRComprehensiveStorage\UncompressedOrZlib
-PresentationContext196 = DRAFT_SRDetailStorage\UncompressedOrZlib
-PresentationContext197 = DRAFT_SRTextStorage\UncompressedOrZlib
-PresentationContext198 = DRAFT_WaveformStorage\UncompressedOrZlib
+PresentationContext195 = DRAFT_RTBeamsDeliveryInstructionStorage\UncompressedOrZlib
+PresentationContext196 = DRAFT_SRAudioStorage\UncompressedOrZlib
+PresentationContext197 = DRAFT_SRComprehensiveStorage\UncompressedOrZlib
+PresentationContext198 = DRAFT_SRDetailStorage\UncompressedOrZlib
+PresentationContext199 = DRAFT_SRTextStorage\UncompressedOrZlib
+PresentationContext200 = DRAFT_WaveformStorage\UncompressedOrZlib
#
# DICOS Storage
#
-PresentationContext199 = DICOS_CTImageStorage\AnyTransferSyntax
-PresentationContext200 = DICOS_DigitalXRayImageStorageForPresentation\AnyTransferSyntax
-PresentationContext201 = DICOS_DigitalXRayImageStorageForProcessing\AnyTransferSyntax
-PresentationContext202 = DICOS_2DAITStorage\AnyTransferSyntax
-PresentationContext203 = DICOS_3DAITStorage\AnyTransferSyntax
-PresentationContext204 = DICOS_QuadrupoleResonanceStorage\UncompressedOrZlib
-PresentationContext205 = DICOS_ThreatDetectionReportStorage\UncompressedOrZlib
+PresentationContext201 = DICOS_CTImageStorage\AnyTransferSyntax
+PresentationContext202 = DICOS_DigitalXRayImageStorageForPresentation\AnyTransferSyntax
+PresentationContext203 = DICOS_DigitalXRayImageStorageForProcessing\AnyTransferSyntax
+PresentationContext204 = DICOS_2DAITStorage\AnyTransferSyntax
+PresentationContext205 = DICOS_3DAITStorage\AnyTransferSyntax
+PresentationContext206 = DICOS_QuadrupoleResonanceStorage\UncompressedOrZlib
+PresentationContext207 = DICOS_ThreatDetectionReportStorage\UncompressedOrZlib
#
# DICONDE Storage
#
-PresentationContext206 = DICONDE_EddyCurrentImageStorage\AnyTransferSyntax
-PresentationContext207 = DICONDE_EddyCurrentMultiframeImageStorage\AnyTransferSyntax
-PresentationContext208 = DICONDE_ThermographyImageStorage\AnyTransferSyntax
-PresentationContext209 = DICONDE_ThermographyMultiFrameImageStorage\AnyTransferSyntax
+PresentationContext208 = DICONDE_EddyCurrentImageStorage\AnyTransferSyntax
+PresentationContext209 = DICONDE_EddyCurrentMultiframeImageStorage\AnyTransferSyntax
+PresentationContext210 = DICONDE_ThermographyImageStorage\AnyTransferSyntax
+PresentationContext211 = DICONDE_ThermographyMultiFrameImageStorage\AnyTransferSyntax
+PresentationContext212 = DICONDE_UltrasoundWaveformStorage\UncompressedOrZlib
# ----------------------------------------------------------------------------
# - VisualAcuityMeasurementsStorage
# - VLWholeSlideMicroscopyImageStorage
# - VolumeRenderingVolumetricPresentationStateStorage
+# - WaveformAcquisitionPresentationStateStorage
# - WaveformAnnotationSRStorage
+# - WaveformPresentationStateStorage
# - WideFieldOphthalmicPhotographyStereographicProjectionImageStorage
# - WideFieldOphthalmicPhotography3DCoordinatesImageStorage
# - XAPerformedProcedureProtocolStorage
# - DICONDE_EddyCurrentMultiframeImageStorage
# - DICONDE_ThermographyImageStorage
# - DICONDE_ThermographyMultiFrameImageStorage
+# - DICONDE_UltrasoundWaveformStorage
# ============================================================================
[[SCPSCURoleSelection]]
Role178 = VariableModalityLUTSoftcopyPresentationStateStorage\BOTH
Role179 = VisualAcuityMeasurementsStorage\BOTH
Role180 = VolumeRenderingVolumetricPresentationStateStorage\BOTH
-Role181 = WaveformAnnotationSRStorage\BOTH
-Role182 = XADefinedProcedureProtocolStorage\BOTH
-Role183 = XAPerformedProcedureProtocolStorage\BOTH
-Role184 = XAXRFGrayscaleSoftcopyPresentationStateStorage\BOTH
-Role185 = XRayRadiationDoseSRStorage\BOTH
-Role186 = RETIRED_StandaloneCurveStorage\BOTH
-Role187 = RETIRED_StandaloneModalityLUTStorage\BOTH
-Role188 = RETIRED_StandaloneOverlayStorage\BOTH
-Role189 = RETIRED_StandalonePETCurveStorage\BOTH
-Role190 = RETIRED_StandaloneVOILUTStorage\BOTH
-Role191 = RETIRED_StoredPrintStorage\BOTH
-Role192 = DRAFT_RTBeamsDeliveryInstructionStorage\BOTH
-Role193 = DRAFT_SRAudioStorage\BOTH
-Role194 = DRAFT_SRComprehensiveStorage\BOTH
-Role195 = DRAFT_SRDetailStorage\BOTH
-Role196 = DRAFT_SRTextStorage\BOTH
-Role197 = DRAFT_WaveformStorage\BOTH
-Role198 = DICOS_CTImageStorage\BOTH
-Role199 = DICOS_DigitalXRayImageStorageForPresentation\BOTH
-Role200 = DICOS_DigitalXRayImageStorageForProcessing\BOTH
-Role201 = DICOS_2DAITStorage\BOTH
-Role202 = DICOS_3DAITStorage\BOTH
-Role203 = DICOS_QuadrupoleResonanceStorage\BOTH
-Role204 = DICOS_ThreatDetectionReportStorage\BOTH
-Role205 = DICONDE_EddyCurrentImageStorage\BOTH
-Role206 = DICONDE_EddyCurrentMultiframeImageStorage\BOTH
-Role207 = DICONDE_ThermographyImageStorage\BOTH
-Role208 = DICONDE_ThermographyMultiFrameImageStorage\BOTH
+Role181 = WaveformAcquisitionPresentationStateStorage\BOTH
+Role182 = WaveformAnnotationSRStorage\BOTH
+Role183 = WaveformPresentationStateStorage\BOTH
+Role184 = XADefinedProcedureProtocolStorage\BOTH
+Role185 = XAPerformedProcedureProtocolStorage\BOTH
+Role186 = XAXRFGrayscaleSoftcopyPresentationStateStorage\BOTH
+Role187 = XRayRadiationDoseSRStorage\BOTH
+Role188 = RETIRED_StandaloneCurveStorage\BOTH
+Role189 = RETIRED_StandaloneModalityLUTStorage\BOTH
+Role190 = RETIRED_StandaloneOverlayStorage\BOTH
+Role191 = RETIRED_StandalonePETCurveStorage\BOTH
+Role192 = RETIRED_StandaloneVOILUTStorage\BOTH
+Role193 = RETIRED_StoredPrintStorage\BOTH
+Role194 = DRAFT_RTBeamsDeliveryInstructionStorage\BOTH
+Role195 = DRAFT_SRAudioStorage\BOTH
+Role196 = DRAFT_SRComprehensiveStorage\BOTH
+Role197 = DRAFT_SRDetailStorage\BOTH
+Role198 = DRAFT_SRTextStorage\BOTH
+Role199 = DRAFT_WaveformStorage\BOTH
+Role200 = DICOS_CTImageStorage\BOTH
+Role201 = DICOS_DigitalXRayImageStorageForPresentation\BOTH
+Role202 = DICOS_DigitalXRayImageStorageForProcessing\BOTH
+Role203 = DICOS_2DAITStorage\BOTH
+Role204 = DICOS_3DAITStorage\BOTH
+Role205 = DICOS_QuadrupoleResonanceStorage\BOTH
+Role206 = DICOS_ThreatDetectionReportStorage\BOTH
+Role207 = DICONDE_EddyCurrentImageStorage\BOTH
+Role208 = DICONDE_EddyCurrentMultiframeImageStorage\BOTH
+Role209 = DICONDE_ThermographyImageStorage\BOTH
+Role210 = DICONDE_ThermographyMultiFrameImageStorage\BOTH
+Role211 = DICONDE_UltrasoundWaveformStorage\BOTH
# ============================================================================
[[Profiles]]
/*
*
- * Copyright (C) 1993-2018, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* @param assoc pointer to DIMSE association
* @param msgid DIMSE message ID
* @param pr DIMSE priority
+ * @param secureConnect a flag indicating whether or not a secure connection was requested
*/
DcmQueryRetrieveMoveContext(
DcmQueryRetrieveDatabaseHandle& handle,
DIC_US priorstatus,
T_ASC_Association *assoc,
DIC_US msgid,
- T_DIMSE_Priority pr)
+ T_DIMSE_Priority pr,
+ OFBool secureConnect)
: dbHandle(handle)
, options_(options)
, associationConfiguration_(associationConfiguration)
, nCompleted(0)
, nFailed(0)
, nWarning(0)
+ , secureConnection(secureConnect)
{
origAETitle[0] = '\0';
origHostName[0] = '\0';
/// number of completed sub-operations that causes warnings
DIC_US nWarning;
+ /// a flag indicating whether or not a secure connection was requested
+ OFBool secureConnection;
};
#endif
/*
*
- * Copyright (C) 1993-2017, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/// profile name for outgoing association configuration
OFString outgoingProfile;
+
+ /// secure connection requested?
+ OFBool secureConnectionRequested_;
+
};
/*
*
- * Copyright (C) 1993-2021, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofstd.h"
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* needed on Solaris for O_RDONLY */
-#endif
END_EXTERN_C
static void getSubOpProgressCallback(void * /* callbackData */,
/* shared lock image file */
int lockfd;
#ifdef O_BINARY
- lockfd = open(fname, O_RDONLY | O_BINARY, 0666);
+ lockfd = open(fname, O_RDONLY | O_BINARY);
#else
- lockfd = open(fname, O_RDONLY , 0666);
+ lockfd = open(fname, O_RDONLY);
#endif
if (lockfd < 0) {
/* due to quota system the file could have been deleted */
/*
*
- * Copyright (C) 1993-2022, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofstd.h"
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* needed on Solaris for O_RDONLY */
-#endif
END_EXTERN_C
/* shared lock image file */
int lockfd;
#ifdef O_BINARY
- lockfd = open(fname, O_RDONLY | O_BINARY, 0666);
+ lockfd = open(fname, O_RDONLY | O_BINARY);
#else
- lockfd = open(fname, O_RDONLY , 0666);
+ lockfd = open(fname, O_RDONLY);
#endif
if (lockfd < 0) {
/* due to quota system the file could have been deleted */
DCMQRDB_ERROR("moveSCP: Cannot create Association-params for sub-ops: " << DimseCondition::dump(temp_str, cond));
}
}
+
+ if (cond.good()) {
+ // use the same network protocol family for incoming and outgoing connections
+ ASC_setProtocolFamily(params, dcmIncomingProtocolFamily.get());
+
+ cond = ASC_setTransportLayerType(params, options_.secureConnectionRequested_);
+ if (cond.bad()) {
+ DCMQRDB_ERROR("moveSCP: Cannot create TLS transport layer for sub-ops: " << DimseCondition::dump(temp_str, cond));
+ }
+ }
+
if (cond.good()) {
OFStandard::snprintf(dstHostNamePlusPort, sizeof(DIC_NODENAME), "%s:%d", dstHostName, dstPortNumber);
ASC_setPresentationAddresses(params, OFStandard::getHostName().c_str(),
if (cond.bad()) {
DCMQRDB_ERROR(DimseCondition::dump(temp_str, cond));
}
+ else {
+ cond = ASC_setTransportLayerType(params, secureConnection);
+ if (cond.bad()) {
+ DCMQRDB_ERROR(DimseCondition::dump(temp_str, cond));
+ }
+ }
DCMQRDB_DEBUG("Request Parameters:" << OFendl << ASC_dumpParameters(temp_str, params, ASC_ASSOC_RQ));
}
if (cond.good()) {
if (cond.good()) {
assocStarted = OFTrue;
}
+
return cond;
}
/*
*
- * Copyright (C) 1993-2024, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
va_list ap;
va_start(ap, fmt);
-
-#if defined(HAVE_VSNPRINTF) && defined(HAVE_PROTOTYPE_VSNPRINTF)
char buf[4096];
#ifdef HAVE_PROTOTYPE_STD__VSNPRINTF
buf[4095] = '\0';
DCMQRDB_ERROR("CONFIG Error: " << buf << "!");
-#else
- fprintf(stderr, "CONFIG Error: ");
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "!\n");
-#endif
va_end(ap);
}
/*
*
- * Copyright (C) 1993-2024, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
DB_FindAttr( DCM_PatientBirthTime, PATIENT_LEVEL, OPTIONAL_KEY ),
DB_FindAttr( DCM_RETIRED_OtherPatientIDs, PATIENT_LEVEL, OPTIONAL_KEY ),
DB_FindAttr( DCM_OtherPatientNames, PATIENT_LEVEL, OPTIONAL_KEY ),
- DB_FindAttr( DCM_EthnicGroup, PATIENT_LEVEL, OPTIONAL_KEY ),
+ DB_FindAttr( DCM_RETIRED_EthnicGroup, PATIENT_LEVEL, OPTIONAL_KEY ),
DB_FindAttr( DCM_PatientComments, PATIENT_LEVEL, OPTIONAL_KEY ),
DB_FindAttr( DCM_IssuerOfPatientID, PATIENT_LEVEL, OPTIONAL_KEY ),
DB_FindAttr( DCM_StudyDate, STUDY_LEVEL, REQUIRED_KEY ),
idx -> param[RECORDIDX_OtherPatientNames]. XTag = DCM_OtherPatientNames ;
idx -> param[RECORDIDX_OtherPatientNames]. ValueLength = PN_MAX_LENGTH ;
idx -> OtherPatientNames[0] = '\0' ;
- idx -> param[RECORDIDX_EthnicGroup]. XTag = DCM_EthnicGroup ;
+ idx -> param[RECORDIDX_EthnicGroup]. XTag = DCM_RETIRED_EthnicGroup ;
idx -> param[RECORDIDX_EthnicGroup]. ValueLength = SH_MAX_LENGTH ;
idx -> EthnicGroup[0] = '\0' ;
idx -> param[RECORDIDX_StudyDate]. XTag = DCM_StudyDate ;
/* only char string type tags are supported at the moment */
char *s = NULL;
dcelem->getString(s);
+
/* the available space is always elem.ValueLength+1 */
- OFStandard::strlcpy(elem.PValueField, s, elem.ValueLength+1);
+ if (s) OFStandard::strlcpy(elem.PValueField, s, elem.ValueLength+1);
+ else elem.PValueField[0]='\0';
}
/** If element is the Query Level, store it in handle
*/
/* only char string type tags are supported at the moment */
char *s = NULL;
dcelem->getString(s);
+
/* the available space is always elem.ValueLength+1 */
- OFStandard::strlcpy(elem.PValueField, s, elem.ValueLength+1);
+ if (s) OFStandard::strlcpy(elem.PValueField, s, elem.ValueLength+1);
+ else elem.PValueField[0]='\0';
}
/** If element is the Query Level, store it in handle
#ifdef LOCK_IMAGE_FILES
int lockfd;
#ifdef O_BINARY
- lockfd = open(imgFile, O_RDWR | O_BINARY, 0666); /* obtain file descriptor */
+ lockfd = open(imgFile, O_RDWR | O_BINARY); /* obtain file descriptor */
#else
- lockfd = open(imgFile, O_RDWR, 0666); /* obtain file descriptor */
+ lockfd = open(imgFile, O_RDWR); /* obtain file descriptor */
#endif
if (lockfd < 0) {
DCMQRDB_WARN("DB ERROR: cannot open image file for deleting: " << imgFile);
/*
*
- * Copyright (C) 1993-2021, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
, associationConfigFile()
, incomingProfile()
, outgoingProfile()
+, secureConnectionRequested_(OFFalse)
{
}
/*
*
- * Copyright (C) 1993-2024, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
T_ASC_PresentationContextID presID, DcmQueryRetrieveDatabaseHandle& dbHandle)
{
OFCondition cond = EC_Normal;
- DcmQueryRetrieveMoveContext context(dbHandle, options_, associationConfiguration_, config_, STATUS_Pending, assoc, request->MessageID, request->Priority);
+ DcmQueryRetrieveMoveContext context(dbHandle, options_, associationConfiguration_, config_, STATUS_Pending, assoc, request->MessageID, request->Priority,
+ tlsOptions_.secureConnectionRequested());
DIC_AE aeTitle;
aeTitle[0] = '\0';
/*
*
- * Copyright (C) 1993-2024, OFFIS e.V.
+ * Copyright (C) 1993-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* needed for stat() */
-#endif
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* needed on Solaris for O_RDONLY */
-#endif
END_EXTERN_C
/* ========================================== helper functions ======================================== */
/* shared lock image file */
int lockfd;
#ifdef O_BINARY
- lockfd = open(imgFile, O_RDONLY | O_BINARY, 0666);
+ lockfd = open(imgFile, O_RDONLY | O_BINARY);
#else
- lockfd = open(imgFile, O_RDONLY, 0666);
+ lockfd = open(imgFile, O_RDONLY);
#endif
if (lockfd < 0) {
DCMQRDB_WARN("CTN has deleted image, giving up (no imgFile): "
DCMTK_ADD_EXECUTABLE(drtdump drtdump.cc)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(drtdump dcmrt dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(drtdump dcmrt)
\section drtdump_copyright COPYRIGHT
-Copyright (C) 2010-2024 by OFFIS e.V. and ICSMED AG, Escherweg 2, 26121
+Copyright (C) 2010-2025 by OFFIS e.V. and ICSMED AG, Escherweg 2, 26121
Oldenburg, Germany.
*/
/*
*
* Copyright (c) 2008-2012, OFFIS e.V. and ICSMED AG, Oldenburg, Germany
- * Copyright (C) 2013-2022, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2013-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class DRTTypes
* These error codes can be used in addition to the general purpose
* codes defined in module dcmdata.
*/
-//@{
+///@{
/// error: a value is invalid according to the standard
extern DCMTK_DCMRT_EXPORT const OFConditionConst RT_EC_InvalidValue;
/// error: the object is invalid, see isValid() method in IOD class
extern DCMTK_DCMRT_EXPORT const OFConditionConst RT_EC_InvalidObject;
-//@}
+///@}
// global definitions for logging mechanism provided by the oflog module
PatientBirthTime(DCM_PatientBirthTime),
OtherPatientIDsSequence(),
OtherPatientNames(DCM_OtherPatientNames),
- EthnicGroup(DCM_EthnicGroup),
+ EthnicGroup(DCM_RETIRED_EthnicGroup),
PatientComments(DCM_PatientComments),
PatientSpeciesDescription(DCM_PatientSpeciesDescription),
PatientSpeciesCodeSequence(),
PatientBirthTime(DCM_PatientBirthTime),
OtherPatientIDsSequence(),
OtherPatientNames(DCM_OtherPatientNames),
- EthnicGroup(DCM_EthnicGroup),
+ EthnicGroup(DCM_RETIRED_EthnicGroup),
PatientComments(DCM_PatientComments),
PatientSpeciesDescription(DCM_PatientSpeciesDescription),
PatientSpeciesCodeSequence(),
PatientBirthTime(DCM_PatientBirthTime),
OtherPatientIDsSequence(),
OtherPatientNames(DCM_OtherPatientNames),
- EthnicGroup(DCM_EthnicGroup),
+ EthnicGroup(DCM_RETIRED_EthnicGroup),
PatientComments(DCM_PatientComments),
PatientSpeciesDescription(DCM_PatientSpeciesDescription),
PatientSpeciesCodeSequence(),
PatientBirthTime(DCM_PatientBirthTime),
OtherPatientIDsSequence(),
OtherPatientNames(DCM_OtherPatientNames),
- EthnicGroup(DCM_EthnicGroup),
+ EthnicGroup(DCM_RETIRED_EthnicGroup),
PatientComments(DCM_PatientComments),
PatientSpeciesDescription(DCM_PatientSpeciesDescription),
PatientSpeciesCodeSequence(),
PatientBirthTime(DCM_PatientBirthTime),
OtherPatientIDsSequence(),
OtherPatientNames(DCM_OtherPatientNames),
- EthnicGroup(DCM_EthnicGroup),
+ EthnicGroup(DCM_RETIRED_EthnicGroup),
PatientComments(DCM_PatientComments),
PatientSpeciesDescription(DCM_PatientSpeciesDescription),
PatientSpeciesCodeSequence(),
/*
*
* Copyright (C) 2008-2012, OFFIS e.V. and ICSMED AG, Oldenburg, Germany
- * Copyright (C) 2013-2023, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2013-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class DRTStructureSetIOD
PatientBirthTime(DCM_PatientBirthTime),
OtherPatientIDsSequence(),
OtherPatientNames(DCM_OtherPatientNames),
- EthnicGroup(DCM_EthnicGroup),
+ EthnicGroup(DCM_RETIRED_EthnicGroup),
PatientComments(DCM_PatientComments),
PatientSpeciesDescription(DCM_PatientSpeciesDescription),
PatientSpeciesCodeSequence(),
PatientBirthTime(DCM_PatientBirthTime),
OtherPatientIDsSequence(),
OtherPatientNames(DCM_OtherPatientNames),
- EthnicGroup(DCM_EthnicGroup),
+ EthnicGroup(DCM_RETIRED_EthnicGroup),
PatientComments(DCM_PatientComments),
PatientSpeciesDescription(DCM_PatientSpeciesDescription),
PatientSpeciesCodeSequence(),
)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(drttest dcmrt dcmdata oflog ofstd)
-DCMTK_TARGET_LINK_MODULES(dcmrt_tests dcmrt dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(drttest dcmrt)
+DCMTK_TARGET_LINK_MODULES(dcmrt_tests dcmrt)
# This macro parses tests.cc and registers all tests
DCMTK_ADD_TESTS(dcmrt)
libsrc-all: include-all
(cd libsrc && $(MAKE) ARCH="$(ARCH)" all)
+
tests-all: libsrc-all
(cd tests && $(MAKE) ARCH="$(ARCH)" all)
(cd include && $(MAKE) clean)
(cd libsrc && $(MAKE) clean)
(cd tests && $(MAKE) clean)
- (cd docs && $(MAKE) clean)
- (cd data && $(MAKE) clean)
- (cd etc && $(MAKE) clean)
rm -f $(TRASH)
distclean:
(cd include && $(MAKE) distclean)
(cd libsrc && $(MAKE) distclean)
(cd tests && $(MAKE) distclean)
- (cd docs && $(MAKE) distclean)
- (cd data && $(MAKE) distclean)
- (cd etc && $(MAKE) distclean)
rm -f $(DISTTRASH)
dependencies:
--- /dev/null
+/*
+ *
+ * Copyright (C) 2023-2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmqi
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Interface of class OverlapUtil
+ *
+ */
+
+#ifndef OVERLAPUTIL_H
+#define OVERLAPUTIL_H
+
+#include "dcmtk/dcmiod/iodtypes.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/ofstd/oftypes.h"
+#include "dcmtk/ofstd/ofvector.h"
+
+class DcmSegmentation;
+
+/** Class that analyzes the frame-based segment structures of a given segmentation object.
+ * It provides the following main functionality:
+ * - Grouping of "physical" frames by their position in space (called "logical frames"), i.e.
+ * frames that are at the same position in space are grouped together.
+ * - For every logical frame (i.e. position in space), it lists the segments found at this
+ * position together with their respective physical frame number
+ * - Return physical frame numbers for a given segment number
+ * - Building an overlap matrix that stores for each arbitrary segment pair whether
+ * they overlap or not.
+ * - Return groups of segments, that no two overlapping segments will be in the same group.
+ * This will not necessarily return the optimal solution, but a solution that should be good enough.
+ * For the method used see getNonOverlappingSegments().
+ */
+class OverlapUtil
+{
+public:
+ /// Image Position Patient tuple (x,y,z)
+ typedef OFVector<Float64> ImagePosition; // might be defined in respective functional group
+
+ /// Physical Frame number with its respective position
+ struct FramePositionAndNumber
+ {
+ /** Default constructor required for vector initialization
+ */
+ FramePositionAndNumber()
+ : m_position()
+ , m_frameNumber(0)
+ {
+ }
+ /** Constructor
+ * @param pos Image position
+ * @param num Physical frame number
+ */
+ FramePositionAndNumber(const ImagePosition& pos, const Uint32& num)
+ : m_position(pos)
+ , m_frameNumber(num)
+ {
+ }
+ /// Frame position in space
+ ImagePosition m_position;
+ /// Physical frame number (number of frame in DICOM object)
+ Uint32 m_frameNumber;
+ };
+
+ /// Physical Frame number with its respective position
+ typedef OFVector<FramePositionAndNumber> FramePositions;
+
+ /// Logical Frame, represented and defined by various physical frames (numbers) at the same position
+ typedef OFVector<Uint32> LogicalFrame;
+
+ /// All distinct positions and for each position the physical frame numbers that can be found at it
+ typedef OFVector<LogicalFrame> DistinctFramePositions;
+
+ /// Lists frames for each segment where segment with index i is represented by the vector at index i,
+ /// and index 0 is unused. I.e. index i is segment number, value is vector of physical frame numbers.
+ typedef OFVector<OFVector<Uint32> > FramesForSegment;
+
+ /// Implements comparision operator to be used for sorting of frame positions,
+ /// making the sorting order depend on the coordinate given in the constructor
+ struct ComparePositions
+ {
+ /** Constructor, used to configure coordinate position to be used for sorting
+ * @param c Coordinate position to be used for sorting
+ */
+ ComparePositions(size_t c)
+ : m_coordinate(c)
+ {
+ }
+
+ /** Compare two frames
+ * @param a First frame to compare
+ * @param b Second frame to compare
+ * @return Returns true if a is less than b based on the coordinate used for sorting
+ */
+ bool operator()(const FramePositionAndNumber& a, const FramePositionAndNumber& b) const
+ {
+ return a.m_position[m_coordinate] < b.m_position[m_coordinate];
+ }
+ /// Coordinate position (0-2, i.e. x,x,z) to be used for sorting
+ size_t m_coordinate;
+ };
+
+ /// Matrix of N x N segment numbers, where N is the number of segments.
+ /// Value is 1 at x,y if x and y overlap, 0 if they don't overlap, and -1 if not initialized.
+ typedef OFVector<OFVector<Sint8> > OverlapMatrix;
+
+ /// Group of non-overlapping segments (each represented by its segment number)
+ typedef OFVector<OFVector<Uint32> > SegmentGroups;
+
+ /** Represents a segment number and a logical frame number it is found at
+ */
+ struct SegNumAndFrameNum
+ {
+ /** Constructor
+ * @param s Segment number
+ * @param f Logical frame number
+ */
+ SegNumAndFrameNum(const Uint16 s, const Uint32 f)
+ : m_segmentNumber(s)
+ , m_frameNumber(f)
+ {
+ }
+ /** Default constructor
+ */
+ SegNumAndFrameNum()
+ : m_segmentNumber(0)
+ , m_frameNumber(0)
+ {
+ }
+
+ /// Segment number as used in DICOM segmentation object (1-n)
+ Uint16 m_segmentNumber;
+ /// Logical frame number (number of frame in DistinctFramePositions vector)
+ Uint32 m_frameNumber;
+ };
+
+ /// Segments and their phyiscal frame number (inner set), grouped by their
+ /// respective logical frame number (outer vector) .The inner vector is not
+ // sorted by segment number but will uniquely contain each segment only once.
+ // A std::set would be more appropriate, but since this is not supported by all
+ // compilers used for DCMTK, we use a vector and check for duplicates manually.
+ typedef OFVector<OFVector<SegNumAndFrameNum> > SegmentsByPosition;
+
+ // ------------------------------------------ Methods ------------------------------------------
+
+ /** Constructor. Use setSegmentationObject() to set the segmentation object to work with.
+ */
+ OverlapUtil();
+
+ /** Destructor */
+ ~OverlapUtil();
+
+ /** Set the segmentation object to work with and clears all old data.
+ * @param seg The segmentation object to work with (not owned by this class)
+ */
+ void setSegmentationObject(DcmSegmentation* seg);
+
+ /** Clears all internal data (except segmentation object reference).
+ * This should be called whenever the input data (i.e. the underlying)
+ * DICOM segmentation object changes, before calling any other method.
+ */
+ void clear();
+
+ /** Get all distinct frame positions and the physical frame numbers at this position
+ * @param result Resulting vector of distinct frame positions
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition getFramesByPosition(DistinctFramePositions& result);
+
+ /** Get all segments and their physical frame number, grouped by their respective logical frame number
+ * @param result Resulting vector of segments grouped by logical frame number
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition getSegmentsByPosition(SegmentsByPosition& result);
+
+ /** Get phyiscal frames for a specific segment by its segment number
+ * @param segmentNumber Segment number to get frames for (1..n)
+ * @param frames Resulting vector of physical frame numbers (first frame is frame 0)
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition getFramesForSegment(const Uint32 segmentNumber, OFVector<Uint32>& frames);
+
+ /** Returns computed overlap matrix
+ * @param matrix Resulting overlap matrix
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition getOverlapMatrix(OverlapMatrix& matrix);
+
+ /** Returns segments grouped together in a way, that no two overlapping
+ * segments will be in the same group. This method does not necessarily
+ * returns the optimal solution, but a solution that should be good enough.
+ * It is guaranteed, that segments in the same group don't overlap.
+ *
+ * It is based on the idea of a greedy algorithm that creates a first group
+ * containing the first segment. Then it goes to the next segment, checks whether
+ * it fits into the first group with no overlaps (easily checked in overlap matrix)
+ * and inserts it into that group if no overlaps exists. Otherwise, it creates a
+ * new group and continues with the next segment (trying to insert it into
+ * the first group, then second group, otherwise creates third group, and so on).
+ * @param segmentGroups Resulting vector of segment groups, each listing the
+ * segment numbers that are in that group
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition getNonOverlappingSegments(SegmentGroups& segmentGroups);
+
+ /** Prints segments by their position in space
+ * @param ss The stream to dump to
+ */
+ void printSegmentsByPosition(OFStringStream& ss);
+
+ /** Prints segment overlap matrix to given stream
+ * @param ss The stream to dump to
+ */
+ void printOverlapMatrix(OFStringStream& ss);
+
+ /** Prints groups of non-overlapping segments (identified by their numbers)
+ * to given stream
+ * @param ss The stream to dump to
+ */
+ void printNonOverlappingSegments(OFStringStream& ss);
+
+ /** Return whether there are at least two segments, that overlap each other.
+ * The overlap matrix is used (and computed if not already done) for this purpose.
+ * @return True if overlapping segments exist, false otherwise
+ */
+ OFBool hasOverlappingSegments();
+
+ /** Returns the absolute value of a floating-point number
+ * @param value The input value
+ * @return The absolute value of the input
+ */
+ static Float64 fabs(const Float64 value);
+
+protected:
+
+
+ /** Group physical frame positions into logical positions. This is done by sorting
+ * frames after *that* position coordinate that in its mean position difference is
+ * larger than slice thickness * 0.9. Then those frames that are close enough to
+ * each other (i.e. distance is smaller than slice thickness * 0.01), end up at the
+ * same logical position (considered a "logical frame")
+ * TODO: This should probably not use mean values for the coordinates
+ * since in some cases, the mean difference in a slice coordinate might be close to 0
+ * if many frames are at the same position. Instead, the maximum difference, variance or
+ * something else could be used?
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition groupFramesByLogicalPosition();
+
+ /** Builds the overlap matrix, if not already done.
+ * @return EC_Normal if successful or already existant, error otherwise
+ */
+ OFCondition buildOverlapMatrix();
+
+ /** Checks if frames are parallel, i.e. if DICOM Image Position Patient is present and
+ * all frames are parallel to each other (i.e. found in the shared functional group)
+ * @return EC_Normal if parallel, SG_EC_FramesNotParallel if image orientation is not shared,
+ * error otherwise
+ */
+ OFCondition ensureFramesAreParallel();
+
+ /** Groups all physical frames by their position. This also works if the physical frames
+ * have slightly different positions, i.e. if they are not exactly the same and are only
+ * "close enough" to be considered the same. Right now, the maximum distance treated equal
+ * is if distance is smaller than slice thickness * 0.01 (i.e. 1% of slice thickness).
+ * Only performs the computation, if not done before.
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition groupFramesByPosition();
+
+ /** Checks whether the given two frames overlap
+ * @param f1 Frame 1, provided by its physical frame number
+ * @param f2 Frame 2, provided by its physical frame number
+ * @param overlap Resulting overlap (overlaps if OFTrue, otherwise not)
+ * @return EC_Normal if successful, error otherwise
+ */
+ OFCondition checkFramesOverlap(const Uint32& f1, const Uint32& f2, OFBool& overlap);
+
+ /** Checks whether the given two frames overlap by using comparing their pixel data
+ * by bitwise "and". This is very efficient, however, only works and is called (right now),
+ * if row*cols % 8 = 0, so we can easily extract frames as binary bitsets without unpacking them.
+ * TODO: Check whether this can be easily extended to other cases as well.
+ * @param f1 Frame 1, provided by its physical frame number
+ * @param f2 Frame 2, provided by its physical frame number
+ * @param f1_data Pixel data of frame 1
+ * @param f2_data Pixel data of frame 2
+ * @param rows Number of rows of the frame(s), not used right now
+ * @param cols Number of columns of the frame(s), not used right now
+ * @param overlap Resulting overlap (overlaps if OFTrue, otherwise not)
+ * @return EC_Normal if successful, error otherwise
+ */
+ static OFCondition checkFramesOverlapBinary(const Uint32& f1,
+ const Uint32& f2,
+ const DcmIODTypes::Frame<Uint8>* f1_data,
+ const DcmIODTypes::Frame<Uint8>* f2_data,
+ const Uint16& /* rows */,
+ const Uint16& /* cols */,
+ OFBool& overlap);
+
+ /** Checks whether the given two frames overlap by using comparing their pixel data
+ * after unpacking, i.e. expanding every bit to a byte, and then comparing whether the two
+ * related bytes of each frame are both non-zero. This is less efficient than checkFramesOverlapBinary(),
+ * @param f1 Frame 1, provided by its physical frame number
+ * @param f2 Frame 2, provided by its physical frame number
+ * @param f1_data Pixel data of frame 1
+ * @param f2_data Pixel data of frame 2
+ * @param rows Number of rows of the frame(s)
+ * @param cols Number of columns of the frame(s)
+ * @param overlap Resulting overlap (overlaps if OFTrue, otherwise not)
+ * @return EC_Normal if successful, error otherwise
+ */
+ static OFCondition checkFramesOverlapUnpacked(const Uint32& f1,
+ const Uint32& f2,
+ const DcmIODTypes::Frame<Uint8>* f1_data,
+ const DcmIODTypes::Frame<Uint8>* f2_data,
+ const Uint16& rows,
+ const Uint16 cols,
+ OFBool& overlap);
+
+ /** Return the most relevant (changing) coordinate, computed by multiplying
+ * x and y vectors of the image orientation and selecting the coordinate
+ * with the largest absolute value.
+ * @param imageOrientation Image orientation patient (3 coordinates for x vector,
+ * 3 coordinates for y vector )
+ * @return 0 if x, 1 if y, 2 if z, 3 if not determinable
+ */
+ static Uint8 identifyChangingCoordinate(const OFVector<Float64>& imageOrientation);
+
+private:
+ /// Image Orientation Patient
+ OFVector<Float64> m_imageOrientation;
+
+ /// Phyiscal frames with their respective positions (IPP)
+ FramePositions m_framePositions;
+
+ /// Outer vector with one entry per segment. Index is the DICOM segment
+ /// number where segment 1 goes to index 0, segment 2 to index 1, and so on.
+ /// Inner vector contains the physical frame numbers that represent the
+ /// segment.
+ FramesForSegment m_framesForSegment;
+
+ /// Logical frames, ie. physical frames with the same position are
+ /// grouped together to a logical frame. For every logical frame, we
+ /// store the related physical frame numbers. The logical frame number
+ /// is implicitly given by the index in the vector.
+ DistinctFramePositions m_logicalFramePositions;
+
+ /// Stores for each logical frame a collection of (paired) segment and
+ /// physical frame number, that exists at that position.
+ SegmentsByPosition m_segmentsByPosition;
+
+ /// Matrix that stores for each segment pair whether they overlap or not.
+ /// I.e. Matrix has size N x N, where N is the number of segments.
+ /// The diagonal is always 0 (no overlap), i.e. a segment never overlaps with itself.
+ /// If there is an overlap, the value is 1.
+ /// If the field is not initialized, the value is -1.
+ OverlapMatrix m_segmentOverlapMatrix;
+
+ //// Groups of segments that do not overlap with each other
+ SegmentGroups m_nonOverlappingSegments;
+
+ /// Reference to segmentation object to work with
+ /// Must be freed outside this class.
+ DcmSegmentation* m_seg;
+};
+
+#endif // OVERLAPUTIL_H
+
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmfg/concatenationcreator.h" // for writing concatenations
#include "dcmtk/dcmfg/concatenationloader.h" // for loading concatenations
#include "dcmtk/dcmfg/fginterface.h" // for multi-frame functional group interface
+#include "dcmtk/dcmfg/fgseg.h" // for FGSegmentation class
#include "dcmtk/dcmiod/iodimage.h" // common image IOD attribute access
-#include "dcmtk/dcmiod/iodmacro.h"
-#include "dcmtk/dcmiod/modenhequipment.h" // for enhanced general equipment module
-#include "dcmtk/dcmiod/modimagepixel.h"
+#include "dcmtk/dcmiod/iodmacro.h" // various macros
+#include "dcmtk/dcmiod/modenhequipment.h" // for enhanced general equipment module
+#include "dcmtk/dcmiod/modimagepixel.h" // for image pixel module
#include "dcmtk/dcmiod/modmultiframedimension.h" // for multi-frame dimension module
+#include "dcmtk/dcmiod/modiccprofile.h" // for ICC profile module
#include "dcmtk/dcmiod/modmultiframefg.h" // for multi-frame functional group module
#include "dcmtk/dcmiod/modsegmentationseries.h" // for segmentation series module
-#include "dcmtk/dcmseg/segdef.h"
+#include "dcmtk/dcmiod/modpalettecolorlut.h" // for palette color LUT module
+#include "dcmtk/dcmseg/segdef.h" //for definitions
+#include "dcmtk/dcmseg/segment.h" // for DcmSegment class
#include "dcmtk/dcmseg/segtypes.h" // for segmentation data types
-#include "dcmtk/ofstd/ofvector.h" // for OFVector
+#include "dcmtk/dcmseg/segutils.h" // fo packBinaryFrame()
+#include "dcmtk/ofstd/ofvector.h" // for OFVector class
+#include "dcmtk/ofstd/ofdiag.h" // for DCMTK_DIAGNOSTIC_PUSH etc.
-// Forward declarations
-class DcmSegment;
class FGSegmentation;
class FGDerivationImage;
class DcmFileFormat;
-/** Class representing an object of the "Segmentation SOP Class".
+/** Class representing an object of the "Segmentation IOD"
+ * or "Label Map Segmentation IOD".
*/
-class DCMTK_DCMSEG_EXPORT DcmSegmentation : public DcmIODImage<IODImagePixelModule<Uint8> >
+
+class DCMTK_DCMSEG_EXPORT DcmSegmentation : public DcmIODImage<IODImagePixelModule<Uint16>, IODImagePixelModule<Uint8> >
{
public:
+
+ struct LoadingFlags;
+
// -------------------- destruction -------------------------------
/** Destructor, frees memory
* @param filename The file to read from
* @param segmentation The resulting segmentation object. NULL if dataset
* could not be read successfully.
+ * @param flags Flags to configure the loading of the segmentation object
+ * @return EC_Normal if reading was successful, error otherwise
+ */
+ static OFCondition loadFile(const OFString& filename, DcmSegmentation*& segmentation, const DcmSegmentation::LoadingFlags& flags = LoadingFlags());
+
+ /** Static method to load a Segmentation object from a file.
+ * The memory of the resulting Segmentation object has to be freed by the
+ * caller.
+ * @param filename The file to read from
+ * @param segmentation The resulting segmentation object. NULL if dataset
+ * could not be read successfully.
+ * @param flags Flags to configure the loading of the segmentation object
* @return EC_Normal if reading was successful, error otherwise
*/
- static OFCondition loadFile(const OFString& filename, DcmSegmentation*& segmentation);
+ static OFCondition loadFile(const OFFile& filename, DcmSegmentation*& segmentation, const DcmSegmentation::LoadingFlags& flags = LoadingFlags());
/** Static method to load a Segmentation object from a dataset object.
* The memory of the resulting Segmentation object has to be freed by the
* @param dataset The dataset to read from
* @param segmentation The resulting segmentation object. NULL if dataset
* could not be read successfully.
+ * @param flags Flags to configure the loading of the segmentation object
* @return EC_Normal if reading was successful, error otherwise
*/
- static OFCondition loadDataset(DcmDataset& dataset, DcmSegmentation*& segmentation);
+ static OFCondition loadDataset(DcmDataset& dataset, DcmSegmentation*& segmentation, const DcmSegmentation::LoadingFlags& flags = LoadingFlags());
/** Static method to load a concatenation of a DICOM Segmentation instance
* into a DcmSegmentation object.
*/
virtual OFBool getCheckFGOnWrite();
+ /** Set whether attribute values should be checked on writing, i.e. if writing
+ * should fail if attribute values violate their VR, VM, character set or value length.
+ * A missing but required value is always considered an error, independent of this setting.
+ * If set to OFFalse, writing will always succeed, even if attribute value constraints
+ * are violated. A warning instead of an error will be printed to the logger.
+ * @param doCheck If OFTrue, attribute value errors are handled as errors on writing, if OFFalse
+ * any errors are ignored.
+ */
+ virtual void setValueCheckOnWrite(const OFBool doCheck);
+
/** If enabled, dimensions are checked before actual writing.
* This can be very time-consuming if many frames are present.
* Disabling should only be done if the user knows that the functional groups
*/
virtual OFBool getCheckDimensionsOnWrite();
+ /** Get input transfer syntax. Returns EXS_Unknown if object has been
+ * created from scratch (and not from file or dataset). If the
+ * segmentation has been loaded from a concatenation, the value
+ * will be EXS_Unknown.
+ * @return Input transfer syntax
+ */
+ virtual E_TransferSyntax getInputTransferSyntax() const;
+
// -------------------- creation ---------------------
/** Factory method to create a binary segmentation object from the minimal
const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo,
const ContentIdentificationMacro& contentIdentification);
+ /** Factory method to create a labelmap segmentation object from the minimal
+ * set of information required. The actual segments and the frame data is
+ * added separately.
+ * The memory of the resulting Segmentation object has to be freed by the
+ * caller.
+ * @param segmentation The resulting segmentation object if provided data is
+ * valid. Otherwise NULL is returned.
+ * @param rows Number of rows of segmentation frame data
+ * @param columns Number of rows of segmentation frame data
+ * @param equipmentInfo Equipment that is responsible for creating the
+ * segmentation. All attributes in equipmentInfo must have
+ * non-empty values.
+ * @param contentIdentification Basic content identification information
+ * @param use16Bit Denote whether to use 16 bit pixel data, i.e
+ * allow for more than 255 segments (labels) in the segmentation
+ * object (up to 65535). If OFTrue, 16 bit pixel data is used,
+ * otherwise 8 bit.
+ * @param colorModel The color model to be used for the labelmap. Default
+ * is MONOCHROME2, alternative is PALETTE.
+ * @return EC_Normal if creation was successful, error otherwise
+ */
+ static OFCondition createLabelmapSegmentation(DcmSegmentation*& segmentation,
+ const Uint16 rows,
+ const Uint16 columns,
+ const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo,
+ const ContentIdentificationMacro& contentIdentification,
+ const OFBool use16Bit,
+ const DcmSegTypes::E_SegmentationLabelmapColorModel colorModel = DcmSegTypes::SLCM_MONOCHROME2);
+
/** Factory method to create a fractional segmentation object from the minimal
* set of information required. The actual segments and the frame data is
* added separately.
// -------------------- access ---------------------
+ OFBool has16BitPixelData() const;
+
+ Uint16 getRows();
+
+ Uint16 getColumns();
+
/** Get number of frames, based on the number of items in the shared
* functional functional groups sequence (i.e.\ the attribute Number of
* Frames) is not trusted). Note that this returns the numbers of frames
* @param segmentNumber The logical segment number
* @return The segment if segment number is valid, NULL otherwise
*/
- virtual DcmSegment* getSegment(const size_t segmentNumber);
+ virtual DcmSegment* getSegment(const Uint16 segmentNumber);
+
+ /** Get all segments
+ * @return The resulting segments
+ */
+ virtual const OFMap<Uint16, DcmSegment*>& getSegments();
/** Get logical segment number by providing a pointer to a given segment
* @param segment The segment to find the logical segment number for
* @param frameNo The number of the frame to get (starting with 0)
* @return The frame requested or NULL if not existing
*/
- virtual const DcmIODTypes::Frame* getFrame(const size_t& frameNo);
+ virtual const DcmIODTypes::FrameBase* getFrame(const size_t& frameNo);
/** Get the frame numbers that belong to a specific segment number
* @param segmentNumber The segment to search frames for
/** Add segment to segmentation object
* @param seg The segment that should be added
- * @param segmentNumber The logical segment number that was assigned for
- * this segment. Contains 0 if adding failed.
+ * @param segmentNumber Depending on the type of segmentation, this
+ * parameter is handled differently:
+ * - For binary and fractional segmentations the segment number
+ * is automatically assigned and will be returned in this
+ * parameter. It is assigned from 0 onwards, i.e. the first
+ * segment added will have segment number 1, the second 2, etc.
+ * - For labelmap segmentations, the segment number is taken from
+ * this parameter and can be >= 0. If the segment number is
+ * already used, the method will overwrite an old segment with
+ * this number.
* @return EC_Normal if adding was successful, error otherwise
*/
virtual OFCondition addSegment(DcmSegment* seg, Uint16& segmentNumber);
/** Add frame to segmentation object
* @param pixData Pixel data to be added. Length must be rows*columns bytes.
- * For binary segmentations (bit depth i.e.\ Bits
- * Allocated/Stored=1), each byte equal to 0 will be interpreted as
- * "not set", while every other value is interpreted as "set". For
- * fractional segmentations the full byte is copied as is.
+ * - For binary segmentations (bit depth i.e.\ Bits
+ * Allocated/Stored=1), each byte equal to 0 will be interpreted as
+ * "not set", while every other value is interpreted as "set".
+ * - For fractional segmentations the full byte is copied as is.
+ * - For labelmap segmentations, the value of each byte is interpreted
+ * as the segment number. In that case the segmentNumber parameters
+ * is ignored.
* @param segmentNumber The logical segment number (>=1) this frame refers to.
* The segment identified by the segmentNumber must already exist.
+ * For labelmap segmentations, this parameter is ignored.
* @param perFrameInformation The functional groups that identify this frame (i.e.
* which are planned to be not common for all other frames). The
* functional groups are copied, so ownership of each group stays
* with the caller no matter what the method returns.
* @return EC_Normal if adding was successful, error otherwise
*/
- virtual OFCondition
- addFrame(Uint8* pixData, const Uint16 segmentNumber, const OFVector<FGBase*>& perFrameInformation);
+ template <typename T>
+ OFCondition addFrame(T* pixData, const Uint16 segmentNumber, const OFVector<FGBase*>& perFrameInformation);
/** Return reference to content content identification of this segmentation object
* @return Reference to content identification data
*/
virtual IODMultiframeDimensionModule& getDimensions();
+ /** Return reference to ICC Profile Module
+ * @return Reference to ICC Profile Module
+ */
+ virtual IODICCProfileModule& getICCProfile();
+
+ /** Return reference to Palette Color Lookup Table module
+ * @return Reference to Palette Color Lookup Table module
+ */
+ virtual IODPaletteColorLUTModule& getPaletteColorLUT();
+
/** Set lossy compression flag of the segmentation object to "01". If one of the
* source images of this segmentation has undergone lossy compression then
* this function should be called.
*/
virtual OFCondition importFromSourceImage(const OFString& filename, const OFBool takeOverCharset = OFTrue);
+ /// Flags for loading segmentation objects. These flags can be used to
+ /// configure the loading of segmentation objects.
+ struct LoadingFlags
+ {
+ // Number of threads to use for reading per-frame functional groups
+ // (will also be applied to writing, if applicable later on)
+ Uint32 m_numThreads;
+
+ // Transfer syntax to use for reading/writing.
+ // transfer syntax used to read the data (auto detection if EXS_Unknown)
+ E_TransferSyntax m_readTransferSyntax;
+
+ /** Constructor to initialize the flags */
+ LoadingFlags() : m_numThreads(1), m_readTransferSyntax(EXS_Unknown) {}
+
+ /** Clear all flags to their default values */
+ void clear()
+ {
+ m_numThreads = 1;
+ m_readTransferSyntax = EXS_Unknown;
+ }
+ };
+
+
protected:
+
/** Protected default constructor. Library users should the factory create..()
* method in order to create an object from scratch
*/
- DcmSegmentation();
+ template <typename ImagePixel>
+ DcmSegmentation(OFin_place_type_t(ImagePixel));
/** Overwrites DcmIODImage::read()
* @param dataset The dataset to read from
*/
OFCondition readWithoutPixelData(DcmItem& dataset);
- /** Writes the complete dataset without pixel data
+ /** Writes the complete dataset without pixel data, and write pixel data separately.
+ * Version for 8 bit pixel data.
* @param dataset The dataset to write to
* @param pixData Buffer for pixel data to write to
* @param pixDataLength Length of pixData buffer
*/
OFCondition writeWithSeparatePixelData(DcmItem& dataset, Uint8*& pixData, size_t& pixDataLength);
+ /** Writes the complete dataset without pixel data, and write pixel data separately
+ * Version for 16 bit pixel data.
+ * @param dataset The dataset to write to
+ * @param pixData Buffer for pixel data to write to
+ * @param pixDataLength Length of pixData buffer
+ * @return EC_Normal if writing succeeded, error otherwise
+ */
+ OFCondition writeWithSeparatePixelData(DcmItem& dataset, Uint16*& pixData, size_t& pixDataLength);
+
/** Create those data structures common for binary and fractional
* segmentations
* @param segmentation The segmentation object created
* @param columns The number of columns for the segmentation
* @param equipmentInfo Equipment information
* @param contentIdentification Content meta information
+ * @param bitsAllocated The number of bits allocated for the pixel data
+ * 8 for binary and fractional segmentations, 8 or 16 for labelmaps
* @return EC_Normal if creation was successful, error otherwise
*/
static OFCondition createCommon(DcmSegmentation*& segmentation,
const Uint16 rows,
const Uint16 columns,
const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo,
- const ContentIdentificationMacro& contentIdentification);
+ const ContentIdentificationMacro& contentIdentification,
+ const Uint16 bitsAllocated);
- /** Hide same function from IODImage since do not want the user to access
- * the image pixel module manually.
- * @return The Image Pixel Module
+ /** Creates segmentation object with pixel data matching required bit depths (as defined by Bits Allocated)
+ * @param item The item to read Bits Allocated from (1, 8 or 16 bits permitted)
+ * @param segmentation The segmentation object to create
+ * @return EC_Normal if creation was successful, error otherwise
*/
- virtual IODImagePixelModule<Uint8>& getImagePixel();
+ static OFCondition createRequiredBitDepth(DcmItem& item, DcmSegmentation*& segmentation);
+
+ /** Creates segmentation object with pixel data matching given bit depths
+ * @param bitsAllocated The Bits Allocated value to use (1, 8 or 16 permitted)
+ * @param segmentation The segmentation object to create
+ * @return EC_Normal if creation was successful, error otherwise
+ */
+ static OFCondition createRequiredBitDepth(const Uint16 bitsAllocated, DcmSegmentation*& segmentation);
+
/** Initialize IOD rules
*/
* @param pixData The filled pixel data buffer returned by the method
* @return EC_Normal if writing was successful, error otherwise
*/
- OFCondition writeFractionalFrames(Uint8* pixData);
+ template <typename T>
+ OFCondition writeByteBasedFrames(T* pixData);
/** Write binary frames to given given pixel data buffer
* @param pixData The filled pixel data buffer returned by the method
*/
virtual OFCondition readFrames(DcmItem& dataset);
+ /** Read pixel data from given pixel data element
+ * @param pixelData The pixel data element to read from
+ * @param numFrames The number of frames expected in the pixel data element
+ * @param pixelsPerFrame The number of pixels per frame (rows*columns)
+ * @param bitsAlloc Bits Allocated value (1, 8 or 16)
+ * @return EC_Normal if reading was successful, error otherwise
+ */
+ virtual OFCondition readPixelData(DcmElement* pixelData, const size_t numFrames, const size_t pixelsPerFrame, const Uint16 bitsAlloc);
+
/** Get Image Pixel module attributes and perform some basic checking
* @param dataset Item to read from, usually main dataset level
* @param allocated Bits Allocated
* Pixel data is copied so it must be freed by the caller.
* @return EC_Normal if adding was successful, error otherwise
*/
- virtual OFCondition addFrame(Uint8* pixData);
+ template <typename T>
+ OFCondition addFrame(T* pixData);
+
+ /** Determine color model. The color model is always MONOCHROME2, except for
+ * labelmaps where PALETTE is permitted. This method checks whether the
+ * we have a labelmap and if returns the correct string for setting Photometric
+ * Interpretation based on desired color model setting (m_LabelmapColorModel).
+ * If unknown color model is requested, MONOCHROME2 and a warning is printed.
+ * @return The color model string for Photometric Interpretation attribute.
+ */
+ OFString determineColorModel();
+
+ /** Checks whether color model found in photometricInterpretation parameter is valid,
+ * i.e. MONOCHROME2, or in case of labelmaps MONOCHROME2 or PALETTE.
+ * Sets internal flag m_labelmapColorModel (for labelmaps) accordingly.
+ * @param photometricInterpretation The color model to check
+ * (e.g. MONOCHROME2, PALETTE, etc.)
+ * @return OFTrue if color model is valid, OFFalse otherwise
+ */
+ OFBool checkColorModel(const OFString& photometricInterpretation);
+
+ /** Sets the SOP Class UID based on the segmentation type,
+ * i.e. whether it is a binary or fractional (Segmentation Storage SOP Class)
+ * or a labelmap segmentation (Labelmap Segmentation Storage SOP Class).
+ * The SOP Class UID is set to the following values:
+ * If the segmentation type is unknown, the SOP Class UID is set to
+ * Segmentation Storage SOP Class as well but a warning is printed.
+ */
+ void setSOPClassUIDBasedOnSegmentationType();
private:
+
+ struct SetRowsAndCols;
+ struct SetImagePixelModuleVisitor;
+
// Modules supported:
//
// Patient Module (through DcmIODImage)
// Enhanced General Equipment Module (through DcmIODImage)
// General Image Module (through DcmIODImage)
// Image Pixel Module (through DcmIODImage)
+ // Palette Color LUT Module (through this class)
// Segmentation Image Module (through this class)
// Multi-frame Functional Group Module
// Multi-Frame Dimension Module
/// Multi-frame Dimension Module
IODMultiframeDimensionModule m_DimensionModule;
+ /// Palette Color LUT Module
+ IODPaletteColorLUTModule m_PaletteColorLUTModule;
+
+ /// ICC Profile
+ IODICCProfileModule m_ICCProfileModule;
+
/// Binary frame data
- OFVector<DcmIODTypes::Frame*> m_Frames;
+ OFVector<DcmIODTypes::FrameBase*> m_Frames;
+
+ /// Denotes whether 16 bit pixel data is used
+ OFBool m_16BitPixelData;
+
+ /// Denotes in case of label maps the color model to be used
+ /// (only relevant for label maps, ignored for binary and fractional segmentations)
+ DcmSegTypes::E_SegmentationLabelmapColorModel m_LabelmapColorModel;
/* Image level information */
/// Maximum Fractional Value: (US, 1, 1C) (required if fractional type is FRACTIONAL)
DcmUnsignedShort m_MaximumFractionalValue;
- /// Segment descriptions from Segment Sequence
- OFVector<DcmSegment*> m_Segments;
+ /// Segment descriptions from Segment Sequence.
+ /// Maps Segment Number to Segment Description data.
+ /// For Labelmaps, the Segment Number is the label value, i.e. the pixel
+ /// value used in the pixel data to denote the segment.
+ OFMap<Uint16, DcmSegment*> m_Segments;
/// Multi-frame Functional Groups high level interface
FGInterface m_FGInterface;
+ /// Input transfer syntax; can be EXS_Unknown if object has been
+ /// created from scratch (and not from file or dataset). If the
+ /// segmentation has been loaded from a concatenation, the value
+ /// will be EXS_Unknown.
+ E_TransferSyntax m_inputXfer;
+
// --------------- private helper functions -------------------
/** Clear old data
* @param pixelData The Pixel Data element
* @param rows Number of rows
* @param cols Number of columns
+ * @param bytesPerPixel Bytes per pixel (1 for 1 or 8 bit data, or 2 for 16 bit data)
* @param numberOfFrames Number of frames
* @result OFTrue if length is valid, OFFalse otherwise
*/
OFBool
- checkPixDataLength(DcmElement* pixelData, const Uint16 rows, const Uint16 cols, const Uint32& numberOfFrames);
+ checkPixDataLength(DcmElement* pixelData, const Uint16 rows, const Uint16 cols, const Uint16 bytesPerPixel, const Uint32& numberOfFrames);
/** Loads file
* @param dcmff The file format to load into
* @param filename The filename of the file to load
* @param dset Pointer to dataset after loading
+ * @param xfer Transfer syntax to use for reading
+ * (if EXS_Unknown,the default, auto detection is used)
* @return EC_Normal if loading was successful, error otherwise
*/
- static OFCondition loadFile(DcmFileFormat& dcmff, const OFString& filename, DcmDataset*& dset);
+ static OFCondition loadFile(DcmFileFormat& dcmff, const OFString& filename, DcmDataset*& dset, const E_TransferSyntax xfer);
/** Computes the number of total bytes required for the frame data of this
* segmentation object. Takes into account dimensions and number of frames,
* size_t type is not able to hold the result of intermediate computations.
* @param rows Number of rows of a frame
* @param cols Number of cols of a frame
+ * @param bytesPerPixel Bytes per pixel (use 1 for 1 or 8 bit data, or 2 for 16 bit data)
* @param numberOfFrames The number of frames of the object
* @param bytesRequired Will hold the result of the computation,
* if successful. Does not any padding into account.
* otherwise.
*/
OFCondition
- getTotalBytesRequired(const Uint16& rows, const Uint16& cols, const Uint32& numberOfFrames, size_t& bytesRequired);
+ getTotalBytesRequired(const Uint16& rows, const Uint16& cols, const Uint16& bytesPerPixel, const Uint32& numberOfFrames, size_t& bytesRequired);
/** Read Fractional Type of segmentation.
* @param item The item to read from
static OFCondition decompress(DcmDataset& dset);
};
+
+template <typename T>
+OFCondition DcmSegmentation::addFrame(T* pixData)
+{
+ if (m_Frames.size() >= DCM_SEG_MAX_FRAMES)
+ return SG_EC_MaxFramesReached;
+
+ OFCondition result;
+ Uint16 rows = 0;
+ Uint16 cols = 0;
+ if (getImagePixel().getRows(rows).good() && getImagePixel().getColumns(cols).good())
+ {
+ DcmIODTypes::Frame<T>* frame = NULL;
+
+ // Diagnostic push/pop for Visual Studio that disables
+ // warning on constant expressions, in this case the
+ // if statement if (sizeof(T) != 1) which is known for
+ // each template instantiation at compile time. One can
+ // use constexpr if available to avoid this warning but this
+ // is not available in all cases
+ #include DCMTK_DIAGNOSTIC_PUSH
+ #include DCMTK_DIAGNOSTIC_IGNORE_VISUAL_STUDIO_CONSTANT_EXPRESSION_WARNING
+ switch (m_SegmentationType)
+ {
+ case DcmSegTypes::ST_BINARY:
+ {
+ if (sizeof(T) != 1) // 8 bit pixel data
+ {
+ DCMSEG_ERROR("Cannot add frame: 16 bit pixel data expected but 8 bit pixel data provided");
+ result = IOD_EC_InvalidPixelData;
+ break;
+ }
+ // Pack the binary frame
+ frame = DcmSegUtils::packBinaryFrame<T>(pixData, rows, cols);
+ if (!frame)
+ result = IOD_EC_CannotInsertFrame;
+ break;
+ }
+ case DcmSegTypes::ST_FRACTIONAL:
+ case DcmSegTypes::ST_LABELMAP:
+ {
+ frame = new DcmIODTypes::Frame<T>(rows * cols);
+
+ if (frame)
+ {
+ if (frame->m_pixData)
+ {
+ memcpy(frame->m_pixData, pixData, frame->getLengthInBytes());
+ }
+ else
+ {
+ delete frame;
+ result = EC_MemoryExhausted;
+ }
+ }
+ else
+ result = EC_MemoryExhausted;
+ break;
+ }
+ case DcmSegTypes::ST_UNKNOWN:
+ default:
+ result = SG_EC_UnknownSegmentationType;
+ break;
+ }
+ // re-enable diagnostic warnings
+ #include DCMTK_DIAGNOSTIC_POP
+ if (result.good())
+ {
+ m_Frames.push_back(frame);
+ }
+ }
+ else
+ {
+ DCMSEG_ERROR("Cannot add frame since rows and/or columns are unknown");
+ result = IOD_EC_CannotInsertFrame;
+ }
+ return result;
+}
+
+
+/** Add frame to segmentation object
+ * @param pixData Pixel data to be added. Length must be rows*columns bytes.
+ * - For binary segmentations (bit depth i.e.\ Bits
+ * Allocated/Stored=1), each byte equal to 0 will be interpreted as
+ * "not set", while every other value is interpreted as "set".
+ * - For fractional segmentations the full byte is copied as is.
+ * - For labelmap segmentations, the value of each byte is interpreted
+ * as the segment number. In that case the segmentNumber parameters
+ * is ignored.
+ * @param segmentNumber The logical segment number (>=1) this frame refers to.
+ * The segment identified by the segmentNumber must already exist.
+ * For labelmap segmentations, this parameter is ignored.
+ * @param perFrameInformation The functional groups that identify this frame (i.e.
+ * which are planned to be not common for all other frames). The
+ * functional groups are copied, so ownership of each group stays
+ * with the caller no matter what the method returns.
+ * @return EC_Normal if adding was successful, error otherwise
+ */
+template <typename T>
+OFCondition
+DcmSegmentation::addFrame(T* pixData, const Uint16 segmentNumber, const OFVector<FGBase*>& perFrameInformation)
+{
+ if (m_Frames.size() >= DCM_SEG_MAX_FRAMES)
+ return SG_EC_MaxFramesReached;
+
+ if (m_16BitPixelData && (sizeof(T) != 2))
+ {
+ DCMSEG_ERROR("Cannot add frame: 16 bit pixel data expected but 8 bit pixel data provided");
+ return IOD_EC_InvalidPixelData;
+ }
+ else if (!m_16BitPixelData && (sizeof(T) == 2))
+ {
+ DCMSEG_ERROR("Cannot add frame: 8 bit pixel data expected but 16 bit pixel data provided");
+ return IOD_EC_InvalidPixelData;
+ }
+
+ Uint32 frameNo = OFstatic_cast(Uint32, m_Frames.size()); // will be the index of the frame (counted from 0)
+ OFCondition result;
+
+ // Check input parameters
+ if (pixData == NULL)
+ {
+ DCMSEG_ERROR("No pixel data provided or zero length");
+ result = EC_IllegalParameter;
+ }
+ if (segmentNumber == 0)
+ {
+ if (m_SegmentationType != DcmSegTypes::ST_LABELMAP)
+ {
+ DCMSEG_ERROR("Cannot add frame: Segment number 0 is not permitted for segmentation type "
+ << DcmSegTypes::segtype2OFString(m_SegmentationType));
+ result = SG_EC_NoSuchSegment;
+ }
+ // we ignore the segment number for label maps
+ }
+ // If this is not a labelmap, check if segment the frame refers to actually exists
+ else if ((m_SegmentationType != DcmSegTypes::ST_LABELMAP) && (getSegment(segmentNumber) == NULL) )
+ {
+ DCMSEG_ERROR("Cannot add frame: Segment with given number " << segmentNumber << " does not exist");
+ result = SG_EC_NoSuchSegment;
+ }
+ if (result.bad())
+ return result;
+
+ OFVector<FGBase*>::const_iterator it = perFrameInformation.begin();
+ while (it != perFrameInformation.end())
+ {
+ // Labelmap is not permitted to have Segmentation Functional Group,
+ // and for other segmentation types we create it automatically, ignore if found
+ if ((*it)->getType() == DcmFGTypes::EFG_SEGMENTATION)
+ {
+ if (m_SegmentationType == DcmSegTypes::ST_LABELMAP)
+ {
+ DCMSEG_WARN("Ignoring provided Segmentation Functional Group, not permitted for labelmap segmentation");
+ it++;
+ continue;
+ }
+ else
+ {
+ DCMSEG_WARN("Ignoring provided Segmentation Functional Group, will be created automatically");
+ it++;
+ continue;
+ }
+ }
+ result = (*it)->check();
+ if (result.bad())
+ {
+ DCMSEG_ERROR("Could not add new frame since functional group of type: "
+ << (*it)->getType() << " is invalid: " << result.text());
+ break;
+ }
+ result = m_FGInterface.addPerFrame(frameNo, *(*it));
+ if (result.bad())
+ {
+ DCMSEG_ERROR("Could not add new frame since functional group of type " << (*it)->getType() << ": "
+ << result.text());
+ break;
+ }
+ it++;
+ }
+
+ // Now also add Segmentation Functional Group
+ if (result.good() && (m_SegmentationType != DcmSegTypes::ST_LABELMAP))
+ {
+ FGSegmentation seg;
+ result = seg.setReferencedSegmentNumber(segmentNumber);
+ if (result.good())
+ {
+ result = m_FGInterface.addPerFrame(frameNo, seg);
+ }
+ else
+ {
+ DCMSEG_ERROR("Could not add new frame, invalid segment number " << segmentNumber << ": " << result.text());
+ }
+ }
+
+ // Insert pixel data
+ if (result.good())
+ {
+ result = addFrame<T>(pixData);
+ }
+
+ // Cleanup any per-frame groups that might have been inserted and return
+ if (result.bad())
+ {
+ for (OFVector<FGBase*>::const_iterator it2 = perFrameInformation.begin(); it2 != perFrameInformation.end();
+ it2++)
+ {
+ m_FGInterface.deletePerFrame(frameNo, (*it2)->getType());
+ }
+ }
+
+ return result;
+}
+
+
#endif // SEGDOC_H
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmdata/dcvrus.h"
#include "dcmtk/dcmiod/iodmacro.h"
-#include "dcmtk/dcmseg/segdoc.h"
#include "dcmtk/dcmseg/segtypes.h"
#include "dcmtk/dcmdata/dcvrui.h"
#include "dcmtk/dcmdata/dcvrlo.h"
#include "dcmtk/dcmdata/dcvrut.h"
-/** Class representing a segment from the Segment Identification Sequence,
- * as used within the Segmentation Image Module. It includes the Segment
- * Description Macro.
- */
+class DcmSegmentation;
+/** Class that represents a Segment inside a Segmentation object.
+ * It mostly represents data as found in an item of the Segment Identification
+ * Sequence (Segmentation Image Module).
+ */
class DCMTK_DCMSEG_EXPORT DcmSegment
{
const DcmSegTypes::E_SegmentAlgoType algoType,
const OFString& algoName = "");
+ /** Make a clone of this segment.
+ * Note that the reference to DcmSegmentation is copied, if not provided in the parameter.
+ * @param seg Pointer to the DcmSegmentation object to associate with the cloned segment,
+ * copied from the original segment if not provided
+ * @return Pointer to the cloned segment if successful, OFnullptr otherwise
+ */
+ DcmSegment* clone(DcmSegmentation* seg = NULL);
+
+ /** Assignment operator, performs deep copy
+ * @param rhs The right-hand side segment to assign from
+ * @return Reference to this segment
+ */
+ DcmSegment& operator=(const DcmSegment& rhs);
+
+ /** Copy constructor
+ * @param rhs The right-hand side segment to copy from
+ */
+ DcmSegment(const DcmSegment& rhs);
+
// ---------------- writing --------------------
/** Write segment to given item which is usually contained within
*/
virtual OFCondition setTrackingUID(const OFString& value, const OFBool checkValue = OFTrue);
+ /** THIS IS ONLY FOR INTERNAL USE. DO NOT USE this as a regular API user.
+ * Get Segment Number as read from the Segment Sequence for this segment.
+ * It may be different from the Segment Number as returned by getSegmentNumber(),
+ * i.e. do not rely on this method for anything.
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual Uint16 getSegmentNumberRead();
+
+ OFshared_ptr<IODRules> getIODRules();
+
/// The utility class must access the protected default constructor
friend class DcmIODUtil;
void referenceSegmentationDoc(DcmSegmentation* doc);
private:
- /** Private undefined copy constructor
- */
- DcmSegment(const DcmSegment&);
-
- /** Private undefined assignment operator
- * @return Reference to "this" class
- */
- DcmSegment& operator=(const DcmSegment&);
/// The segmentation document where this segment is located in
DcmSegmentation* m_SegmentationDoc;
+ /// The segment number as read from the Segment Number attribute.
+ /// This attribute only holds the number read from the file/item,
+ /// and will be updated only during a write process. It is not meant
+ /// to be used by the API user at all but only for internal purposes.
+ DcmUnsignedShort m_SegmentNumber;
+
/// Segment Description Macro
SegmentDescriptionMacro m_SegmentDescription;
DcmUniqueIdentifier m_TrackingUID;
/// Rules for data elements within this IOD
- IODRules m_Rules;
+ OFshared_ptr<IODRules> m_Rules;
};
#endif // SEGMENT_H
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
* These error codes can be used in addition to the general purpose
* codes defined in module dcmdata.
*/
-//@{
+///@{
/// error: specified functional group is already existing
extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_MaxSegmentsReached;
extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NotEnoughData;
/// error: too many frames
extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_MaxFramesReached;
+/// error: invalid bit depth
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_InvalidBitDepth;
+/// error: frames are not parallel
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_FramesNotParallel;
+/// error: no segmentation SOP class (Segmentation or Label Map Segmentation SOP Class)
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NoSegmentationBasedSOPClass;
+/// error: segmentation-based object does not require conversion
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_NoConversionRequired;
+/// error: cannot convert fractional to labelmap segmentations
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_CannotConvertFractionalToLabelmap;
+/// error: segmentation-based object is already a label map
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_AlreadyLabelMap;
+/// error: binary segmentation contains overlapping segments
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_OverlappingSegments;
+/// error: cannot convert to PALETTE color model since not all segments contain Recommended Display CIELab Value Macro
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_CannotConvertMissingCIELab;
+/// error: missing Plane Position (Patient) Functional Group
+extern DCMTK_DCMSEG_EXPORT const OFConditionConst SG_EC_MissingPlanePositionPatient;
+
+///@}
/** General purpose class hiding global functions, constants and types in the
* segmentation context from the global namespace.
ST_BINARY,
/// Fractional segmentation where fraction specifies how much of voxel
/// is occupied by the segment
- ST_FRACTIONAL
+ ST_FRACTIONAL,
+ /// Labelmap segmentation where each segment is assigned a unique
+ // integer value in the pixel data (EXPERIMENTAL: based on Supplement 243 public comment 2014-01-08)
+ ST_LABELMAP
};
/** Segment Algorithm Type
SFT_OCCUPANCY
};
+ /** Labelmap Segmentation desired color model
+ */
+ enum E_SegmentationLabelmapColorModel
+ {
+ /// Unknown (e.g.\ not initialized)
+ SLCM_UNKNOWN,
+ /// Monochrome 1 Bit
+ SLCM_MONOCHROME2,
+ /// Palette Color
+ SLCM_PALETTE
+ };
+
// -- helper functions --
/** Return string representation of algorithm type
* @return The fractional type as enum value
*/
static DcmSegTypes::E_SegmentationFractionalType OFString2FractionalType(const OFString& value);
+
+ /** Returns string representation from labelmap color enum type
+ * @param value The labelmap color model as enum value
+ * @param fallbackValue The value to use if the enum value is unknown or invalid (not used if empty)
+ * @return The labelmap color model as a string
+ */
+ static OFString labelmapColorModel2OFString(const DcmSegTypes::E_SegmentationLabelmapColorModel value, const OFString& fallbackValue="");
+
+ /** Return enum representation of photometric interpretation type string as found in
+ * segmentation objects.
+ * @param value The photometric interpretation type as a string
+ * @return The photometric interpretation type as enum value
+ */
+ static DcmSegTypes::E_SegmentationLabelmapColorModel OFString2LabelmapColorModel(const OFString& value);
};
/** Class representing the Segmented Property Type Code and Segmented
*/
virtual ~SegmentedPropertyTypeCodeItem();
+ /** Clone method, creates a new instance of this class and performs
+ * a deep copy of all data.
+ * @return Pointer to newly created SegmentedPropertyTypeCodeItem object. The
+ * caller is responsible for deleting the object after use.
+ */
+ virtual SegmentedPropertyTypeCodeItem* clone();
+
+ /** Assignment operator, performs deep copy
+ * @param rhs The right-hand side SegmentedPropertyTypeCodeItem to assign from
+ * @return Reference to this SegmentedPropertyTypeCodeItem
+ */
+ SegmentedPropertyTypeCodeItem& operator=(const SegmentedPropertyTypeCodeItem& rhs);
+
+ /** Copy constructor
+ * @param rhs The right-hand side SegmentedPropertyTypeCodeItem to copy from
+ */
+ SegmentedPropertyTypeCodeItem(const SegmentedPropertyTypeCodeItem& rhs);
+
/** Clear all data
*/
virtual void clearData();
*/
virtual ~SegmentDescriptionMacro();
+ /** Clone method, creates a new instance of this class and performs
+ * a deep copy of all data.
+ * @return Pointer to newly created SegmentDescriptionMacro object. The
+ * caller is responsible for deleting the object after use.
+ */
+ virtual SegmentDescriptionMacro* clone();
+
+ /** Assignment operator, performs deep copy
+ * @param rhs The right-hand side SegmentDescriptionMacro to assign from
+ * @return Reference to this SegmentDescriptionMacro
+ */
+ SegmentDescriptionMacro& operator=(const SegmentDescriptionMacro& rhs);
+
/** Clear all data
*/
virtual void clearData();
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmseg/segdef.h"
#include "dcmtk/dcmseg/segtypes.h"
+#include "dcmtk/dcmiod/iodtypes.h"
#include "dcmtk/ofstd/oftypes.h"
#include "dcmtk/ofstd/ofvector.h"
* @param columns The number of columns in the pixel data
* @return The frame data if successful, NULL if an error occurs
*/
- static DcmIODTypes::Frame* packBinaryFrame(const Uint8* pixelData, const Uint16 rows, const Uint16 columns);
+ template <typename T>
+ static DcmIODTypes::Frame<T>* packBinaryFrame(const T* pixelData, const Uint16 rows, const Uint16 columns);
/** Concatenate given frames into a single bit array
* @param frames The frames to concatenate. Each frame is expected to be in packed format (1 bit per pixel),
* @param pixDataLength The length of the pixData buffer in bytes
* @return EC_Normal if successful, an error code otherwise
*/
- static OFCondition concatBinaryFrames(const OFVector<DcmIODTypes::Frame*>& frames, const Uint16 rows, const Uint16 cols, Uint8* pixData, const size_t pixDataLength);
+ static OFCondition concatBinaryFrames(const OFVector<DcmIODTypes::FrameBase*>& frames, const Uint16 rows, const Uint16 cols, Uint8* pixData, const size_t pixDataLength);
/** Unpacks a binary segmentation frame into a "sparse" pixel data frame where
* every resulting byte represents a single bit of the frame being either
* @param cols The cols of the frame
* @return The segmentation frame in unpacked format. NULL in case of error.
*/
- static DcmIODTypes::Frame* unpackBinaryFrame(const DcmIODTypes::Frame* frame, Uint16 rows, Uint16 cols);
+ static DcmIODTypes::Frame<Uint8>*
+ unpackBinaryFrame(const DcmIODTypes::Frame<Uint8>* frame, Uint16 rows, Uint16 cols);
/** Dumps a byte as binary number to a string. Only useful for
* otherwise bytes are enumerated
*/
static void debugDumpBin(Uint8* buffer, size_t length, const OFString& what, const OFBool raw);
+
};
+/** Pack the given segmentation pixel data, provided "unpacked", into
+ * the packed format expected by DICOM. This is the default version which prints an error
+ * and returns NULL.
+ * @return Returns NULL
+ */
+template<typename T>
+DcmIODTypes::Frame<T>*
+DcmSegUtils::packBinaryFrame(const T*, const Uint16, const Uint16)
+{
+ // Return error since this function is not specialized for T
+ DCMSEG_ERROR("packBinaryFrame() can only be used for Uint8 data but you provided something else");
+ return NULL;
+}
+
+/** Pack the given segmentation pixel data, provided "unpacked", into
+ * the packed format expected by DICOM. This is the 8 bit version which
+ * is the only version actually used for segmentation objects.
+ * @param pixelData Pixel data in unpacked format, i.e on byte per pixel, either 0 (not set) or non-0 (set)
+ * @param rows Number of rows in the pixel data
+ * @param columns The number of columns in the pixel data
+ * @return Frame data if successful, NULL if an error occurs
+ */
+template<>
+inline DcmIODTypes::Frame<Uint8>*
+DcmSegUtils::packBinaryFrame(const Uint8* pixelData, const Uint16 rows, const Uint16 columns)
+{
+ // Sanity checking
+ const size_t totalBits = OFstatic_cast(size_t, rows) * columns;
+ if (totalBits == 0)
+ {
+ DCMSEG_ERROR("Unable to pack binary segmentation frame: Rows or Columns is 0");
+ return NULL;
+ }
+ if (!pixelData)
+ {
+ DCMSEG_ERROR("Unable to pack binary segmentation frame: No pixel data provided");
+ return NULL;
+ }
+
+ // Calculate total number of bytes required
+ size_t totalBytes = (totalBits + 7) / 8; // +7 to round up to the nearest byte
+
+ // Allocate memory for the packed bit array
+ Uint8* packedData = new Uint8[totalBytes];
+ if (packedData == NULL)
+ {
+ DCMSEG_ERROR("Cannot allocate memory for packed binary frame");
+ return NULL;
+ }
+ memset(packedData, 0, totalBytes); // Initialize to 0
+
+ // Pack the bits
+ for (Uint32 i = 0; i < totalBits; ++i) {
+ if (pixelData[i] != 0) {
+ Uint32 byteIndex = i / 8;
+ Uint32 bitIndex = i % 8;
+ DCMSEG_TRACE("bitIndex: " << bitIndex << ", byteIndex: " << byteIndex << ", packedData[byteIndex]: " << DcmSegUtils::debugByte2Bin(packedData[byteIndex]));
+ packedData[byteIndex] |= (1 << bitIndex); // Fill from right to left
+ }
+ }
+
+ // Create and return the frame
+ DcmIODTypes::Frame<Uint8>* frame = new DcmIODTypes::Frame<Uint8>();
+ if (frame == NULL)
+ {
+ DCMSEG_ERROR("Cannot allocate memory for packed binary frame");
+ delete[] packedData;
+ return NULL;
+ }
+ frame->m_pixData = packedData;
+ frame->m_numPixels = totalBytes; // for binary frames, numPixels must be set to the number of bytes used
+ return frame; // Return the packed frame
+}
+
+
#endif // SEGUTILS_H
# create library from source files
DCMTK_ADD_LIBRARY(dcmseg
+ overlaputil.cc
segdoc.cc
segment.cc
segtypes.cc
-segdoc.o: segdoc.cc ../../config/include/dcmtk/config/osconfig.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
- ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+overlaputil.o: overlaputil.cc ../include/dcmtk/dcmseg/overlaputil.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../config/include/dcmtk/config/osconfig.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
- ../../ofstd/include/dcmtk/ofstd/ofexport.h \
../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
- ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
../../ofstd/include/dcmtk/ofstd/ofstring.h \
../../ofstd/include/dcmtk/ofstd/ofstream.h \
- ../../ofstd/include/dcmtk/ofstd/ofstd.h \
- ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../ofstd/include/dcmtk/ofstd/ofdiag.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../dcmfg/include/dcmtk/dcmfg/framesorter.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmath.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fg.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgpixmsr.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
+ ../include/dcmtk/dcmseg/segdoc.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modfor.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvriant.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/stralias.def \
+ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modiccprofile.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segment.h \
+ ../include/dcmtk/dcmseg/segtypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
+ ../include/dcmtk/dcmseg/segutils.h \
+ ../../ofstd/include/dcmtk/ofstd/oftimer.h
+segdoc.o: segdoc.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../oflog/include/dcmtk/oflog/appender.h \
../../ofstd/include/dcmtk/ofstd/ofmem.h \
../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
../../oflog/include/dcmtk/oflog/layout.h \
../../oflog/include/dcmtk/oflog/streams.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dctag.h \
- ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
- ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../dcmfg/include/dcmtk/dcmfg/fgderimg.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
- ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
- ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
- ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
../../dcmiod/include/dcmtk/dcmiod/iodutil.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../include/dcmtk/dcmseg/segdoc.h \
../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modiccprofile.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \
- ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \
- ../include/dcmtk/dcmseg/segment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segment.h \
+ ../include/dcmtk/dcmseg/segtypes.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
../include/dcmtk/dcmseg/segutils.h
segment.o: segment.cc ../../config/include/dcmtk/config/osconfig.h \
- ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
- ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../ofstd/include/dcmtk/ofstd/ofdefine.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
- ../../ofstd/include/dcmtk/ofstd/ofstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
../../ofstd/include/dcmtk/ofstd/ofstd.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../../ofstd/include/dcmtk/ofstd/oftraits.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
- ../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
- ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../ofstd/include/dcmtk/ofstd/oflimits.h \
../../ofstd/include/dcmtk/ofstd/oferror.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dctag.h \
- ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
- ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmfg/include/dcmtk/dcmfg/fg.h \
../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmiod/include/dcmtk/dcmiod/iodimage.h \
../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modiccprofile.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \
- ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segment.h \
+ ../include/dcmtk/dcmseg/segtypes.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
- ../include/dcmtk/dcmseg/segment.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
+ ../include/dcmtk/dcmseg/segutils.h
segtypes.o: segtypes.cc ../../config/include/dcmtk/config/osconfig.h \
../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../ofstd/include/dcmtk/ofstd/ofcond.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../include/dcmtk/dcmseg/segtypes.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
-I$(dcmdatadir)/include -I$(dcmioddir)/include -I$(dcmfgdir)/include
LOCALDEFS =
-objs = segdoc.o segment.o segtypes.o segutils.o
+objs = overlaputil.o segdoc.o segment.o segtypes.o segutils.o
library = libdcmseg.$(LIBEXT)
--- /dev/null
+/*
+ *
+ * Copyright (C) 2023-2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmqi
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Interface of class OverlapUtil
+ *
+ */
+
+#include "dcmtk/dcmseg/overlaputil.h"
+#include "dcmtk/dcmfg/framesorter.h"
+#include "dcmtk/dcmdata/dcerror.h"
+#include "dcmtk/dcmfg/fginterface.h"
+#include "dcmtk/dcmfg/fgpixmsr.h"
+#include "dcmtk/dcmfg/fgplanor.h"
+#include "dcmtk/dcmfg/fgseg.h"
+#include "dcmtk/dcmfg/fgtypes.h"
+#include "dcmtk/dcmiod/iodtypes.h"
+#include "dcmtk/dcmseg/segdoc.h"
+#include "dcmtk/dcmseg/segtypes.h"
+#include "dcmtk/dcmseg/segutils.h"
+#include "dcmtk/ofstd/ofcond.h"
+#include "dcmtk/ofstd/ofstream.h"
+#include "dcmtk/ofstd/oftimer.h"
+#include "dcmtk/ofstd/oftypes.h"
+
+OverlapUtil::OverlapUtil()
+ : m_imageOrientation()
+ , m_framePositions()
+ , m_framesForSegment()
+ , m_logicalFramePositions()
+ , m_segmentsByPosition()
+ , m_segmentOverlapMatrix(0)
+ , m_nonOverlappingSegments()
+ , m_seg()
+{
+}
+
+OverlapUtil::~OverlapUtil()
+{
+ // nothing to do
+}
+
+void OverlapUtil::setSegmentationObject(DcmSegmentation* seg)
+{
+ m_seg = seg;
+ clear();
+}
+
+void OverlapUtil::clear()
+{
+ m_imageOrientation.clear();
+ m_framePositions.clear();
+ m_framesForSegment.clear();
+ m_logicalFramePositions.clear();
+ m_segmentsByPosition.clear();
+ m_segmentOverlapMatrix.clear();
+ m_nonOverlappingSegments.clear();
+}
+
+OFCondition OverlapUtil::getFramesByPosition(DistinctFramePositions& result)
+{
+ OFCondition cond;
+ if (!m_seg)
+ {
+ DCMSEG_ERROR("getFramesByPosition(): No segmentation object set");
+ return EC_IllegalCall;
+ }
+ if (m_logicalFramePositions.empty())
+ {
+ cond = groupFramesByPosition();
+ }
+ if (cond.good())
+ {
+ result = m_logicalFramePositions;
+ }
+ return cond;
+}
+
+OFCondition OverlapUtil::getFramesForSegment(const Uint32 segmentNumber, OFVector<Uint32>& frames)
+{
+ if (!m_seg)
+ {
+ DCMSEG_ERROR("getFramesForSegment(): No segmentation object set");
+ return EC_IllegalCall;
+ }
+ if ((segmentNumber == 0) || (segmentNumber > m_seg->getNumberOfSegments()))
+ {
+ DCMSEG_ERROR("getFramesForSegment(): Segment number " << segmentNumber << " is out of range");
+ return EC_IllegalParameter;
+ }
+ if (m_framesForSegment.empty())
+ {
+ FGInterface& fg = m_seg->getFunctionalGroups();
+ size_t tempNum = m_seg->getNumberOfFrames();
+ if (tempNum > 4294967295)
+ {
+ DCMSEG_ERROR("getFramesForSegment(): Number of frames " << tempNum << " exceeds maximum number of possible frames (2^32-1)");
+ return EC_IllegalParameter;
+ }
+ Uint32 numFrames = static_cast<Uint32>(m_seg->getNumberOfFrames());
+ m_framesForSegment.clear();
+ m_framesForSegment.resize(m_seg->getNumberOfSegments());
+ // Get Segmentation FG for each frame and remember the segment number for each frame
+ // in the vector m_segmentsForFrame
+ for (Uint32 f = 0; f < numFrames; f++)
+ {
+ FGBase* group = NULL;
+ FGSegmentation* segFG = NULL;
+ group = fg.get(f, DcmFGTypes::EFG_SEGMENTATION);
+ segFG = OFstatic_cast(FGSegmentation*, group);
+ if (segFG)
+ {
+ Uint16 segNum = 0;
+ OFCondition cond = segFG->getReferencedSegmentNumber(segNum);
+ if (cond.good() && segNum > 0)
+ {
+ m_framesForSegment[segNum - 1].push_back(f); // physical frame number for segment
+ }
+ else if (segNum == 0)
+ {
+ DCMSEG_WARN("getFramesForSegment(): Referenced Segment Number is 0 (not permitted) for frame #"
+ << f << ", ignoring");
+ return EC_InvalidValue;
+ }
+ else
+ {
+ DCMSEG_ERROR(
+ "getFramesForSegment(): Referenced Segment Number not found (not permitted) for frame #"
+ << f << ", cannot add segment");
+ return EC_TagNotFound;
+ }
+ }
+ }
+ }
+ frames = m_framesForSegment[segmentNumber - 1];
+ return EC_Normal;
+}
+
+OFCondition OverlapUtil::ensureFramesAreParallel()
+{
+ FGInterface& fg = m_seg->getFunctionalGroups();
+ OFCondition cond;
+ OFBool perFrame = OFFalse;
+ FGPlaneOrientationPatient* pop = NULL;
+ // Ensure that Image Orientation Patient is shared, i.e. we have parallel frames
+ m_imageOrientation.clear();
+ m_imageOrientation.resize(6);
+ FGBase* group = fg.get(0, DcmFGTypes::EFG_PLANEORIENTPATIENT, perFrame);
+ pop = OFstatic_cast(FGPlaneOrientationPatient*, group);
+ if (pop)
+ {
+ if (perFrame == OFFalse)
+ {
+ DCMSEG_DEBUG("ensureFramesAreParallel(): Image Orientation Patient is shared, frames are parallel");
+ m_imageOrientation.resize(6);
+ cond = pop->getImageOrientationPatient(m_imageOrientation[0],
+ m_imageOrientation[1],
+ m_imageOrientation[2],
+ m_imageOrientation[3],
+ m_imageOrientation[4],
+ m_imageOrientation[5]);
+ DCMSEG_DEBUG("Image Orientation Patient set to : " << m_imageOrientation[0] << ", " << m_imageOrientation[1]
+ << ", " << m_imageOrientation[2] << ", " << m_imageOrientation[3] << ", " << m_imageOrientation[4]
+ << ", " << m_imageOrientation[5]);
+ }
+ else
+ {
+ DCMSEG_ERROR(
+ "ensureFramesAreParallel(): Image Orientation Patient is per-frame, frames are probably not parallel");
+ return SG_EC_FramesNotParallel;
+ }
+ }
+ else
+ {
+ DCMSEG_ERROR(
+ "ensureFramesAreParallel(): Plane Orientation (Patient) FG not found, cannot check for parallel frames");
+ return EC_TagNotFound;
+ }
+ return cond;
+}
+
+OFCondition OverlapUtil::groupFramesByPosition()
+{
+ if (!m_framePositions.empty())
+ {
+ // Already computed
+ return EC_Normal;
+ }
+
+ OFCondition cond = ensureFramesAreParallel();
+ if (cond.bad())
+ {
+ return cond;
+ }
+
+ OFTimer tm;
+
+ // Group all frames by position into m_logicalFramePositions.
+ // After that, all frames at the same position will be in the same vector
+ // assigned to the same key (the frame's coordinates) in the map.
+ // Group all frames by position into m_logicalFramePositions.
+ FrameSorterIPP sorter;
+ sorter.setSorterInput(&(m_seg->getFunctionalGroups()));
+ FrameSorterIPP::Results results;
+ sorter.sort(results);
+ if (results.errorCode.bad())
+ {
+ DCMSEG_ERROR("groupFramesByPosition(): Cannot sort frames by position: " << results.errorCode.text());
+ return results.errorCode;
+ }
+ // Copy results from frame sorter to overlap util framePositions member
+ m_framePositions.clear();
+ m_framePositions.reserve(results.framePositions.size());
+ for (size_t i = 0; i < results.framePositions.size(); ++i)
+ {
+ m_framePositions.push_back(FramePositionAndNumber(results.framePositions[i], results.frameNumbers[i]));
+ }
+ cond = groupFramesByLogicalPosition();
+
+ // print frame groups if debug log level is enabled:
+ if (cond.good() && DCM_dcmsegLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
+ {
+ DCMSEG_DEBUG("groupFramesByPosition(): Frames grouped by position:");
+ for (size_t i = 0; i < m_logicalFramePositions.size(); ++i)
+ {
+ OFStringStream ss;
+ for (size_t j = 0; j < m_logicalFramePositions[i].size(); ++j)
+ {
+ if (j > 0)
+ ss << ", ";
+ ss << m_logicalFramePositions[i][j];
+ }
+ DCMSEG_DEBUG("groupFramesByPosition(): Logical frame #" << i << ": " << ss.str());
+ }
+ }
+ DCMSEG_DEBUG("groupFramesByPosition(): Grouping frames by position took " << tm.getDiff() << " s");
+
+ if (cond.bad())
+ {
+ m_framePositions.clear();
+ m_logicalFramePositions.clear();
+ }
+ return cond;
+}
+
+OFCondition OverlapUtil::getSegmentsByPosition(SegmentsByPosition& result)
+{
+ if (!m_seg)
+ {
+ DCMSEG_ERROR("getSegmentsByPosition(): No segmentation object set");
+ return EC_IllegalCall;
+ }
+ if (!m_segmentsByPosition.empty())
+ {
+ // Already computed
+ result = m_segmentsByPosition;
+ return EC_Normal;
+ }
+ // Make sure prerequisites are met
+ OFTimer tm;
+ OFCondition cond = groupFramesByPosition();
+ if (cond.bad())
+ {
+ return cond;
+ }
+ size_t numSegments = m_seg->getNumberOfSegments();
+ if (m_logicalFramePositions.empty())
+ {
+ cond = getFramesByPosition(m_logicalFramePositions);
+ if (cond.bad())
+ return cond;
+ }
+ m_segmentsByPosition.clear();
+ m_segmentsByPosition.resize(m_logicalFramePositions.size());
+ for (size_t l = 0; l < m_logicalFramePositions.size(); ++l)
+ {
+ OFVector<Uint32> segments;
+ for (size_t f = 0; f < m_logicalFramePositions[l].size(); ++f)
+ {
+ Uint32 frameNumber = m_logicalFramePositions[l][f];
+ OFVector<Uint32> segs;
+ FGBase* group = NULL;
+ FGSegmentation* segFG = NULL;
+ group = m_seg->getFunctionalGroups().get(frameNumber, DcmFGTypes::EFG_SEGMENTATION);
+ segFG = OFstatic_cast(FGSegmentation*, group);
+ if (segFG)
+ {
+ Uint16 segNum = 0;
+ cond = segFG->getReferencedSegmentNumber(segNum);
+ if (cond.good() && segNum > 0 && (segNum <= numSegments))
+ {
+ // check if segment is already in the list for this position
+ // (may happen if multiple frames for same segment are at same position?)
+ OFBool found = OFFalse;
+ for (size_t s = 0; s < m_segmentsByPosition[l].size(); ++s)
+ {
+ if (m_segmentsByPosition[l][s].m_segmentNumber == segNum)
+ {
+ found = OFTrue;
+ break;
+ }
+ }
+ if (!found)
+ {
+ m_segmentsByPosition[l].push_back(SegNumAndFrameNum(segNum, frameNumber));
+ }
+ }
+ else if (segNum == 0)
+ {
+ DCMSEG_ERROR(
+ "getSegmentsByPosition(): Referenced Segment Number is 0 (not permitted), cannot add segment");
+ cond = EC_InvalidValue;
+ break;
+ }
+ else if (segNum > numSegments)
+ {
+ DCMSEG_ERROR("getSegmentsByPosition(): Found Referenced Segment Number "
+ << segNum << " but only " << numSegments
+ << " segments are present, cannot add segment");
+ DCMSEG_ERROR(
+ "getSegmentsByPosition(): Segments are not numbered consecutively, cannot add segment");
+ cond = EC_InvalidValue;
+ break;
+ }
+ else
+ {
+ DCMSEG_ERROR("getSegmentsByPosition(): Referenced Segment Number not found (not permitted) , "
+ "cannot add segment");
+ cond = EC_TagNotFound;
+ break;
+ }
+ }
+ }
+ if (cond.bad())
+ {
+ break;
+ }
+ }
+ // print segments per logical frame if debug log level is enabled
+ if (cond.good() && DCM_dcmsegLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
+ {
+ OFStringStream ss;
+ printSegmentsByPosition(ss);
+ DCMSEG_DEBUG(ss.str());
+ }
+ DCMSEG_DEBUG("groupFramesByPosition(): Grouping segments by position took " << tm.getDiff() << " s");
+ return cond;
+}
+
+OFCondition OverlapUtil::getOverlapMatrix(OverlapMatrix& matrix)
+{
+ if (!m_seg)
+ {
+ DCMSEG_ERROR("getOverlapMatrix(): No segmentation object set");
+ return EC_IllegalCall;
+ }
+ if (!m_segmentOverlapMatrix.empty())
+ {
+ // Already computed
+ matrix = m_segmentOverlapMatrix;
+ return EC_Normal;
+ }
+ // Make sure prerequisites are met
+ OFTimer tm;
+ SegmentsByPosition dontCare;
+ OFCondition result = getSegmentsByPosition(dontCare);
+ if (result.good())
+ {
+ result = buildOverlapMatrix();
+ }
+ if (result.good())
+ {
+ matrix = m_segmentOverlapMatrix;
+ }
+ DCMSEG_DEBUG("getOverlappingSegments(): Building overlap matrix took " << tm.getDiff() << " s");
+ return result;
+}
+
+OFCondition OverlapUtil::getNonOverlappingSegments(SegmentGroups& segmentGroups)
+{
+ if (!m_seg)
+ {
+ DCMSEG_ERROR("getNonOverlappingSegments(): No segmentation object set");
+ return EC_IllegalCall;
+ }
+ OFTimer tm;
+ OFCondition result;
+ if (!m_nonOverlappingSegments.empty())
+ {
+ // Already computed
+ segmentGroups = m_nonOverlappingSegments;
+ return EC_Normal;
+ }
+ // Make sure prerequisites are met
+ result = getOverlapMatrix(m_segmentOverlapMatrix);
+ if (result.good())
+ {
+ // Group those segments from the overlap matrix together, that do not
+ // overlap with each other.
+ // Go through all segments and check if they overlap with any of the already
+ // grouped segments. If not, add them to the same group. If yes, create a new group
+ // and add them there.
+ m_nonOverlappingSegments.push_back(OFVector<Uint32>());
+ for (size_t i = 0; i < m_segmentOverlapMatrix.size(); ++i)
+ {
+ // make sure we can cast this later to Uint32
+ if (i > OFnumeric_limits<Uint32>::max())
+ {
+ DCMSEG_ERROR("getNonOverlappingSegments(): Number of segments "
+ << m_segmentOverlapMatrix.size()
+ << " exceeds maximum number of possible segments (2^32-1)");
+ return EC_IllegalParameter;
+ }
+ // Loop over all groups and check whether the current segment overlaps with any of them
+ OFBool overlaps = OFFalse;
+ for (size_t j = 0; j < m_nonOverlappingSegments.size(); ++j)
+ {
+ // Loop over all segments in the current group
+ for (OFVector<Uint32>::iterator it = m_nonOverlappingSegments[j].begin();
+ it != m_nonOverlappingSegments[j].end();
+ ++it)
+ {
+ // Check if the current segment overlaps with the segment in the current group
+ if (m_segmentOverlapMatrix[i][(*it) - 1] == 1)
+ {
+ overlaps = OFTrue;
+ break;
+ }
+ }
+ if (!overlaps)
+ {
+ // Add segment to current group
+ m_nonOverlappingSegments[j].push_back(OFstatic_cast(Uint32, i) + 1);
+ break;
+ }
+ }
+ if (overlaps)
+ {
+ // Create new group and add segment to it
+ m_nonOverlappingSegments.push_back(OFVector<Uint32>());
+ m_nonOverlappingSegments.back().push_back(OFstatic_cast(Uint32, i) + 1);
+ }
+ }
+ }
+ DCMSEG_DEBUG("getNonOverlappingSegments(): Grouping non-overlapping segments took " << tm.getDiff() << " s");
+ if (result.good())
+ {
+ // print non-overlapping segments if debug log level is enabled
+ if (DCM_dcmsegLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
+ {
+ OFStringStream ss;
+ printNonOverlappingSegments(ss);
+ DCMSEG_DEBUG(ss.str());
+ }
+ }
+ if (result.good())
+ {
+ segmentGroups = m_nonOverlappingSegments;
+ }
+ return result;
+}
+
+OFBool OverlapUtil::hasOverlappingSegments()
+{
+ // Make sure prerequisites are met
+ OFCondition result = getOverlapMatrix(m_segmentOverlapMatrix);
+ if (result.good())
+ {
+ for (size_t i = 0; i < m_segmentOverlapMatrix.size(); ++i)
+ {
+ for (size_t j = 0; j < m_segmentOverlapMatrix[i].size(); ++j)
+ {
+ if (m_segmentOverlapMatrix[i][j] == 1)
+ {
+ return OFTrue;
+ }
+ }
+ }
+ }
+ return OFFalse;
+}
+
+
+Float64 OverlapUtil::fabs(const Float64 value)
+{
+ return (value < 0) ? -value : value;
+}
+
+
+void OverlapUtil::printSegmentsByPosition(OFStringStream& ss)
+{
+ ss << "printSegmentsByPosition(): Segments grouped by logical frame positions, (seg#,frame#):" << OFendl;
+ for (size_t i = 0; i < m_segmentsByPosition.size(); ++i)
+ {
+ OFStringStream tempSS;
+ for (OFVector<SegNumAndFrameNum>::iterator it = m_segmentsByPosition[i].begin();
+ it != m_segmentsByPosition[i].end();
+ ++it)
+ {
+ if (it != m_segmentsByPosition[i].begin())
+ tempSS << ",";
+ tempSS << "(" << (*it).m_segmentNumber << "," << (*it).m_frameNumber << ")";
+ }
+ ss << "printSegmentsByPosition(): Logical frame #" << i << ": " << tempSS.str();
+ }
+}
+
+void OverlapUtil::printOverlapMatrix(OFStringStream& ss)
+{
+ ss << "printOverlapMatrix(): Overlap matrix:" << OFendl;
+ for (size_t i = 0; i < m_segmentOverlapMatrix.size(); ++i)
+ {
+ for (size_t j = 0; j < m_segmentOverlapMatrix[i].size(); ++j)
+ {
+ if (m_segmentOverlapMatrix[i][j] >= 0)
+ ss << OFstatic_cast(Uint32, m_segmentOverlapMatrix[i][j]);
+ else
+ ss << "1";
+ ss << " ";
+ }
+ ss << OFendl;
+ }
+}
+
+void OverlapUtil::printNonOverlappingSegments(OFStringStream& ss)
+{
+ ss << "printNonOverlappingSegments(): Non-overlapping segments:" << OFendl;
+ for (size_t i = 0; i < m_nonOverlappingSegments.size(); ++i)
+ {
+ ss << "Group #" << i << ": ";
+ for (OFVector<Uint32>::iterator it = m_nonOverlappingSegments[i].begin();
+ it != m_nonOverlappingSegments[i].end();
+ ++it)
+ {
+ if (it != m_nonOverlappingSegments[i].begin())
+ ss << ", ";
+ ss << (*it);
+ }
+ ss << OFendl;
+ }
+}
+
+OFCondition OverlapUtil::buildOverlapMatrix()
+{
+ // Make 2 dimensional array matrix of Sint8 type for (segment numbers) X (segment numbers).
+ // Initialize with -1 (not checked yet)
+ m_segmentOverlapMatrix.clear();
+ m_segmentOverlapMatrix.resize(m_seg->getNumberOfSegments());
+ for (size_t i = 0; i < m_segmentOverlapMatrix.size(); ++i)
+ {
+ m_segmentOverlapMatrix[i].resize(m_seg->getNumberOfSegments(), -1);
+ }
+ // Diagonal is always 0 (segment does not interfere/overlap with itself)
+ for (size_t i = 0; i < m_segmentOverlapMatrix.size(); ++i)
+ {
+ m_segmentOverlapMatrix[i][i] = 0;
+ }
+ // Go through all logical frame positions, and compare all segments at each position
+ size_t index1, index2;
+ index1 = index2 = 0;
+ for (size_t i = 0; i < m_segmentsByPosition.size(); ++i)
+ {
+ DCMSEG_TRACE("getOverlappingSegments(): Comparing segments at logical frame position " << i);
+ // Compare all segments at this position
+ for (OFVector<SegNumAndFrameNum>::iterator it = m_segmentsByPosition[i].begin();
+ it != m_segmentsByPosition[i].end();
+ ++it)
+ {
+ index1++;
+ for (OFVector<SegNumAndFrameNum>::iterator it2 = m_segmentsByPosition[i].begin();
+ it2 != m_segmentsByPosition[i].end();
+ ++it2)
+ {
+ index2++;
+ // Skip comparison of same segments in reverse order (index2 < index1)
+ if (index2 <= index1)
+ continue;
+ // Skip self-comparison (diagonal is always 0); (index1==index2)
+ if (it->m_segmentNumber != it2->m_segmentNumber)
+ {
+ // Check if we already have found an overlap on another logical frame, and if so, skip
+ Sint8 existing_result
+ = m_segmentOverlapMatrix[(*it).m_segmentNumber - 1][(*it2).m_segmentNumber - 1];
+ if (existing_result == 1)
+ {
+ DCMSEG_DEBUG("getOverlappingSegments(): Skipping frame comparison on pos #"
+ << i << " for segments " << (*it).m_segmentNumber << " and "
+ << (*it2).m_segmentNumber << " (already marked as overlapping)");
+ continue;
+ }
+ // Compare pixels of the frames referenced by each segments.
+ // If they overlap, mark as overlapping
+ OFBool overlap = OFFalse;
+ checkFramesOverlap(it->m_frameNumber, it2->m_frameNumber, overlap);
+
+ // Enter result into overlap matrix
+ m_segmentOverlapMatrix[(*it).m_segmentNumber - 1][(*it2).m_segmentNumber - 1] = overlap ? 1 : 0;
+ m_segmentOverlapMatrix[(*it2).m_segmentNumber - 1][(*it).m_segmentNumber - 1] = overlap ? 1 : 0;
+ }
+ }
+ }
+ }
+ // Since we don't compare all segments (since not all are showing up together on a single logical frame),
+ // we set all remaining entries that are still not initialized (-1) to 0 (no overlap)
+ for (size_t i = 0; i < m_segmentOverlapMatrix.size(); ++i)
+ {
+ for (size_t j = 0; j < m_segmentOverlapMatrix[i].size(); ++j)
+ {
+ if (m_segmentOverlapMatrix[i][j] == -1)
+ {
+ m_segmentOverlapMatrix[i][j] = 0;
+ }
+ }
+ }
+ // print overlap matrix if debug log level is enabled
+ if (DCM_dcmsegLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
+ {
+ OFStringStream ss;
+ printOverlapMatrix(ss);
+ DCMSEG_DEBUG(ss.str());
+ }
+ return EC_Normal;
+}
+
+OFCondition OverlapUtil::checkFramesOverlap(const Uint32& f1, const Uint32& f2, OFBool& overlap)
+{
+ if (f1 == f2)
+ {
+ // The same frame should not be considered overlapping at all
+ overlap = OFFalse;
+ return EC_Normal;
+ }
+ overlap = OFFalse;
+ OFCondition result;
+ const DcmIODTypes::Frame<Uint8>* f1_data = OFstatic_cast(const DcmIODTypes::Frame<Uint8>*, m_seg->getFrame(f1));
+ const DcmIODTypes::Frame<Uint8>* f2_data = OFstatic_cast(const DcmIODTypes::Frame<Uint8>*, m_seg->getFrame(f2));
+ Uint16 rows, cols;
+ // Cast to DcmSegmentation base class (DcmIodImage)
+ rows = m_seg->getRows();
+ cols = m_seg->getColumns();
+ if (rows * cols % 8 != 0)
+ {
+ // We must compare pixel by pixel of the unpacked frames (for now)
+ result = checkFramesOverlapUnpacked(f1, f2, f1_data, f2_data, rows, cols, overlap);
+ }
+ else
+ {
+ // We can compare byte by byte using bitwise AND (if both have a 1 at the same position, they overlap)
+ result = checkFramesOverlapBinary(f1, f2, f1_data, f2_data, rows, cols, overlap);
+ }
+ if (result.good() && !overlap)
+ {
+ DCMSEG_TRACE("checkFramesOverlap(): Frames " << f1 << " and " << f2 << " don't overlap");
+ }
+ return result;
+}
+
+OFCondition OverlapUtil::checkFramesOverlapBinary(const Uint32& f1,
+ const Uint32& f2,
+ const DcmIODTypes::Frame<Uint8>* f1_data,
+ const DcmIODTypes::Frame<Uint8>* f2_data,
+ const Uint16& /* rows */,
+ const Uint16& /* cols */,
+ OFBool& overlap)
+{
+ DCMSEG_TRACE("checkFramesOverlap(): Comparing frames " << f1 << " and " << f2 << " for overlap (fast binary mode)");
+ if (!f1_data || !f2_data)
+ {
+ DCMSEG_ERROR("checkFramesOverlap(): Cannot access binary frames " << f1 << " and " << f2 << " for comparison");
+ return EC_IllegalCall;
+ }
+ if (f1_data->getLengthInBytes() != f2_data->getLengthInBytes())
+ {
+ DCMSEG_ERROR("checkFramesOverlap(): Frames " << f1 << " and " << f2
+ << " have different length, cannot compare");
+ return EC_IllegalCall;
+ }
+ // Compare byte (8 pixels at once) using bitwise AND (if both have a 1 at the same position, they overlap)
+ for (size_t n = 0; n < f1_data->getLengthInBytes(); ++n)
+ {
+ if (f1_data->m_pixData[n] & f2_data->m_pixData[n])
+ {
+ DCMSEG_DEBUG("checkFramesOverlap(): Frames " << f1 << " and " << f2 << " do overlap, pixel value "
+ << OFstatic_cast(Uint16, f1_data->m_pixData[n]) << " at index "
+ << n << " is the same");
+ overlap = OFTrue;
+ break;
+ }
+ }
+ return EC_Normal;
+}
+
+OFCondition OverlapUtil::checkFramesOverlapUnpacked(const Uint32& f1,
+ const Uint32& f2,
+ const DcmIODTypes::Frame<Uint8>* f1_data,
+ const DcmIODTypes::Frame<Uint8>* f2_data,
+ const Uint16& rows,
+ const Uint16 cols,
+ OFBool& overlap)
+{
+ DCMSEG_TRACE("checkFramesOverlap(): Comparing frames " << f1 << " and " << f2
+ << " for overlap (slow unpacked mode)");
+ OFunique_ptr<DcmIODTypes::Frame<Uint8> > f1_unpacked(DcmSegUtils::unpackBinaryFrame(f1_data, rows, cols));
+ OFunique_ptr<DcmIODTypes::Frame<Uint8> > f2_unpacked(DcmSegUtils::unpackBinaryFrame(f2_data, rows, cols));
+ if (!f1_unpacked || !f2_unpacked)
+ {
+ DCMSEG_ERROR("checkFramesOverlap(): Cannot unpack frames " << f1 << " and " << f2 << " for comparison");
+ return EC_IllegalCall;
+ }
+ if (f1_unpacked->getLengthInBytes() != f2_unpacked->getLengthInBytes())
+ {
+ DCMSEG_ERROR("checkFramesOverlap(): Frames " << f1 << " and " << f2
+ << " have different length, cannot compare");
+ return EC_IllegalCall;
+ }
+ // Compare pixels of both frames and check whether at least one has the same value
+ DCMSEG_TRACE("checkFramesOverlap(): Comparing frames " << f1 << " and " << f2 << " for overlap");
+ for (size_t n = 0; n < f1_unpacked->getLengthInBytes(); ++n)
+ {
+ if (f1_unpacked->m_pixData[n] != 0 && (f1_unpacked->m_pixData[n] == f2_unpacked->m_pixData[n]))
+ {
+ DCMSEG_DEBUG("checkFramesOverlap(): Frames " << f1 << " and " << f2 << " do overlap, pixel value "
+ << OFstatic_cast(Uint16, f1_unpacked->m_pixData[n])
+ << " at index " << n << " is the same");
+ overlap = OFTrue;
+ break;
+ }
+ }
+ return EC_Normal;
+}
+
+
+OFCondition OverlapUtil::groupFramesByLogicalPosition()
+{
+ OFCondition cond;
+ FGInterface& fg = m_seg->getFunctionalGroups();
+ OFBool perFrame = OFFalse;
+ Float64 sliceThickness = 0.0;
+ FGPixelMeasures* pm = NULL;
+ FGBase* group = fg.get(0, DcmFGTypes::EFG_PIXELMEASURES, perFrame);
+ pm = OFstatic_cast(FGPixelMeasures*, group);
+ if (pm)
+ {
+ // Get/compute Slice Thickness
+ cond = pm->getSliceThickness(sliceThickness);
+ if (cond.bad())
+ {
+ DCMSEG_ERROR("groupFramesByPosition(): Cannot get Slice Thickness from Pixel Measures FG: "
+ << cond.text());
+ return cond;
+ }
+ }
+
+ Uint8 relevantCoordinate = identifyChangingCoordinate(m_imageOrientation);
+
+ // vec will contain all frame numbers that are at the same position
+ OFVector<Uint32> vec;
+ vec.push_back(m_framePositions[0].m_frameNumber);
+ m_logicalFramePositions.push_back(vec); // Initialize for first logical frame
+ for (size_t j = 1; j < m_framePositions.size(); ++j)
+ {
+ // If frame is close to previous frame, add it to the same vector.
+ // 2.5 is chosen since it means the frames are not further away if clearly less than half a slice
+ // thickness
+ Float64 diff = OverlapUtil::fabs(m_framePositions[j].m_position[relevantCoordinate]
+ - m_framePositions[j - 1].m_position[relevantCoordinate]);
+ DCMSEG_DEBUG("Coordinates of both frames:");
+ DCMSEG_DEBUG("Frame " << j << ": " << m_framePositions[j].m_position[0] << ", "
+ << m_framePositions[j].m_position[1] << ", "
+ << m_framePositions[j].m_position[2]);
+ DCMSEG_DEBUG("Frame " << j - 1 << ": " << m_framePositions[j - 1].m_position[0] << ", "
+ << m_framePositions[j - 1].m_position[1] << ", "
+ << m_framePositions[j - 1].m_position[2]);
+ DCMSEG_DEBUG("groupFramesByPosition(): Frame " << j << " is " << diff
+ << " mm away from previous frame");
+ // 1% inaccuracy for slice thickness will be considered as same logical position
+ if (diff < sliceThickness * 0.01)
+ {
+ // Add frame to last vector
+ DCMSEG_DEBUG("Assigning to same frame bucket as previous frame");
+ m_logicalFramePositions.back().push_back(
+ m_framePositions[j].m_frameNumber); // physical frame number
+ }
+ else
+ {
+ DCMSEG_DEBUG("Assigning to same new frame bucket");
+ // Create new vector
+ OFVector<Uint32> newVec;
+ newVec.push_back(m_framePositions[j].m_frameNumber);
+ m_logicalFramePositions.push_back(newVec);
+ }
+ }
+
+ return cond;
+}
+
+Uint8 OverlapUtil::identifyChangingCoordinate(const OFVector<Float64>& imageOrientation)
+{
+ Float64 cross_product[3];
+ // Compute cross product of image orientation vectors.
+ // We are only interested into the absolute values for later comparison
+ cross_product[0] = OverlapUtil::fabs(imageOrientation[1] * imageOrientation[5] - imageOrientation[2] * imageOrientation[4]);
+ cross_product[1] = OverlapUtil::fabs(imageOrientation[2] * imageOrientation[3] - imageOrientation[0] * imageOrientation[5]);
+ cross_product[2] = OverlapUtil::fabs(imageOrientation[0] * imageOrientation[4] - imageOrientation[1] * imageOrientation[3]);
+ // Find out which coordinate is changing the most (biggest absolute coordinate value of cross product)
+ if ((cross_product[0] > cross_product[1]) && (cross_product[0] > cross_product[2]))
+ {
+ return 0;
+ }
+ if ((cross_product[1] > cross_product[0]) && (cross_product[1] > cross_product[2]))
+ {
+ return 1;
+ }
+ if ((cross_product[2] > cross_product[0]) && (cross_product[2] > cross_product[1]))
+ {
+ return 2;
+ }
+ // No clear winner
+ return 3;
+}
/*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
*
* All rights reserved. See COPYRIGHT file for details.
*
#include "dcmtk/config/osconfig.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/dcmdata/dctypes.h"
#include "dcmtk/dcmdata/dcuid.h"
+#include "dcmtk/dcmdata/dcxfer.h"
#include "dcmtk/dcmfg/concatenationcreator.h"
#include "dcmtk/dcmfg/fgderimg.h"
#include "dcmtk/dcmfg/fgseg.h"
+#include "dcmtk/dcmiod/iodtypes.h"
#include "dcmtk/dcmiod/iodutil.h"
#include "dcmtk/dcmseg/segdoc.h"
#include "dcmtk/dcmseg/segment.h"
#include "dcmtk/dcmseg/segtypes.h"
#include "dcmtk/dcmseg/segutils.h"
-#include "dcmtk/oflog/loglevel.h"
-#include <cstddef>
+#include "dcmtk/ofstd/ofutil.h"
-// default constructor (protected, instance creation via create() function)
-DcmSegmentation::DcmSegmentation()
- : DcmSegmentation::IODImage(OFin_place<IODImagePixelModule<Uint8> >)
+
+struct DcmSegmentation::SetRowsAndCols
+{
+ SetRowsAndCols(const Uint16 rows, const Uint16 cols)
+ : m_rows(rows)
+ , m_cols(cols)
+ {
+ }
+
+ template <typename T>
+ OFCondition operator()(T& t)
+ {
+ t.setRows(m_rows);
+ t.setColumns(m_cols);
+ return EC_Normal;
+ }
+
+ // Members
+ const Uint16 m_rows;
+ const Uint16 m_cols;
+};
+
+
+struct DcmSegmentation::SetImagePixelModuleVisitor
+{
+ SetImagePixelModuleVisitor(const Uint16 rows, const Uint16 columns, const Uint16 bitsAllocated, const Uint16 bitsStored,
+ const Uint16 highBit, const Uint16 samplesPerPixel, const OFString& photometricInterpretation)
+ : m_rows(rows)
+ , m_cols(columns)
+ , m_bitsAllocated(bitsAllocated)
+ , m_bitsStored(bitsStored)
+ , m_highBit(highBit)
+ , m_samplesPerPixel(samplesPerPixel)
+ , m_photometricInterpretation(photometricInterpretation)
+ , m_pixelRepresentation(2) // invalid default value
+ {
+ }
+
+ template <typename T>
+ OFCondition operator()(T& t)
+ {
+ if ((m_rows == 0) || (m_cols == 0))
+ {
+ DCMSEG_ERROR("Rows/Cols must be non-zero but are : " << m_rows << "/" << m_cols);
+ return IOD_EC_InvalidDimensions;
+ }
+
+ t.setRows(m_rows);
+ t.setColumns(m_cols);
+ t.setBitsAllocated(m_bitsAllocated);
+ t.setBitsStored(m_bitsStored);
+ t.setHighBit(m_highBit);
+ t.setSamplesPerPixel(m_samplesPerPixel);
+ t.setPhotometricInterpretation(m_photometricInterpretation);
+ t.setPixelRepresentation(OFis_signed<T>::value ? 1 : 0);
+
+ return EC_Normal;
+ }
+
+ // Members
+ const Uint16 m_rows;
+ const Uint16 m_cols;
+ const Uint16 m_bitsAllocated;
+ const Uint16 m_bitsStored;
+ const Uint16 m_highBit;
+ const Uint16 m_samplesPerPixel;
+ const OFString m_photometricInterpretation;
+ const Uint16 m_pixelRepresentation;
+
+};
+
+template <typename ImagePixel>
+DcmSegmentation::DcmSegmentation(OFin_place_type_t(ImagePixel))
+ : IODImage(OFin_place<ImagePixel>)
, m_SegmentationSeries(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules())
, m_EnhancedGeneralEquipmentModule(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules())
, m_FG(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules())
, m_DimensionModule(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules())
+ , m_PaletteColorLUTModule(DcmSegmentation::IODImage::getData(), DcmSegmentation::IODImage::getRules())
, m_Frames()
+ , m_16BitPixelData(OFFalse)
+ , m_LabelmapColorModel(DcmSegTypes::SLCM_UNKNOWN)
, m_ImageType("DERIVED\\PRIMARY")
, m_ContentIdentificationMacro()
, m_SegmentationType(DcmSegTypes::ST_BINARY)
, m_MaximumFractionalValue(DCM_MaximumFractionalValue)
, m_Segments()
, m_FGInterface()
+ , m_inputXfer(EXS_Unknown)
{
DcmSegmentation::initIODRules();
}
// ------------ Segmentation Image Module -------------
// Partly overrides rules from General Image Module
- getRules()->addRule(new IODRule(DCM_ImageType, "2", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
- getRules()->addRule(new IODRule(DCM_SegmentationType, "1", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE),
- OFTrue);
- getRules()->addRule(
+ DcmSegmentation::IODImage::getRules()->addRule(
+ new IODRule(DCM_ImageType, "2", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
+ DcmSegmentation::IODImage::getRules()->addRule(
+ new IODRule(DCM_SegmentationType, "1", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
+ DcmSegmentation::IODImage::getRules()->addRule(
new IODRule(DCM_SegmentationFractionalType, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE),
OFTrue);
- getRules()->addRule(
+ DcmSegmentation::IODImage::getRules()->addRule(
new IODRule(DCM_MaximumFractionalValue, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
+ // Instance Number is Type 1 in Segmentation Image Module
+ DcmSegmentation::IODImage::getRules()->addRule(
+ new IODRule(DCM_InstanceNumber, "1", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
+
// Re-use General Image Module instead of Segmentation Image Module
- getRules()->addRule(new IODRule(DCM_LossyImageCompression, "1", "1", "GeneralImageModule", DcmIODTypes::IE_IMAGE),
- OFTrue);
- getRules()->addRule(
+ DcmSegmentation::IODImage::getRules()->addRule(
+ new IODRule(DCM_LossyImageCompression, "1", "1", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
+ DcmSegmentation::IODImage::getRules()->addRule(
new IODRule(DCM_LossyImageCompressionMethod, "1-n", "1C", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
- getRules()->addRule(
+ DcmSegmentation::IODImage::getRules()->addRule(
new IODRule(DCM_LossyImageCompressionRatio, "1-n", "1C", "GeneralImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
- // Override rule from General Series Module
- getRules()->addRule(new IODRule(DCM_ReferencedPerformedProcedureStepSequence,
- "1",
- "1C",
- "SegmentationSeriesModule",
- DcmIODTypes::IE_SERIES),
- OFTrue);
- getRules()->addRule(new IODRule(DCM_SeriesNumber, "1", "1", "SegmentationSeriesModule", DcmIODTypes::IE_SERIES),
- OFTrue);
+ // ------------ Segmentation Series Module -------------
- // Instance Number is also used within Content Identification Macro, disable it there
- m_ContentIdentificationMacro.getIODRules().deleteRule(DCM_InstanceNumber);
+ // Override rule from General Series Module
+ DcmSegmentation::IODImage::getRules()->addRule(new IODRule(DCM_ReferencedPerformedProcedureStepSequence,
+ "1",
+ "1C",
+ "SegmentationSeriesModule",
+ DcmIODTypes::IE_SERIES),
+ OFTrue);
+ DcmSegmentation::IODImage::getRules()->addRule(
+ new IODRule(DCM_SeriesNumber, "1", "1", "SegmentationSeriesModule", DcmIODTypes::IE_SERIES), OFTrue);
}
DcmSegmentation::~DcmSegmentation()
}
// static method for loading segmentation objects
-OFCondition DcmSegmentation::loadFile(const OFString& filename, DcmSegmentation*& segmentation)
+OFCondition DcmSegmentation::loadFile(const OFString& filename, DcmSegmentation*& segmentation, const DcmSegmentation::LoadingFlags& flags)
{
DcmFileFormat dcmff;
DcmDataset* dataset = NULL;
- OFCondition result = loadFile(dcmff, filename, dataset);
+ OFCondition result = loadFile(dcmff, filename, dataset, flags.m_readTransferSyntax);
if (result.bad())
return result;
- return loadDataset(*dataset, segmentation);
+ return loadDataset(*dataset, segmentation, flags);
}
+
// static method for loading segmentation objects
-OFCondition DcmSegmentation::loadDataset(DcmDataset& dataset, DcmSegmentation*& segmentation)
+OFCondition DcmSegmentation::loadDataset(DcmDataset& dataset, DcmSegmentation*& segmentation, const DcmSegmentation::LoadingFlags& flags)
{
segmentation = NULL;
OFCondition result = DcmSegmentation::decompress(dataset);
if (result.bad())
return result;
- DcmSegmentation* temp = new DcmSegmentation();
- if (temp == NULL)
+ DcmSegmentation *temp = NULL;
+ result = createRequiredBitDepth(dataset, temp);
+ if (result.bad())
{
- return EC_MemoryExhausted;
+ return result;
}
-
+ // Apply the loading flags
+ temp->getFunctionalGroups().setUseThreads(flags.m_numThreads);
+ // Start actual reading
result = temp->read(dataset);
if (result.good())
{
segmentation = temp;
+ segmentation->m_inputXfer = dataset.getOriginalXfer();
}
else
{
{
DcmDataset dset;
segmentation = NULL;
- OFVector<DcmIODTypes::Frame*> frames;
+ OFVector<DcmIODTypes::FrameBase*> frames;
OFCondition result = cl.load(concatenationUID, &dset, frames);
if (result.good())
{
- segmentation = new DcmSegmentation();
- if (segmentation)
+ result = createRequiredBitDepth(dset, segmentation);
+ if (result.good())
{
- result = segmentation->readWithoutPixelData(dset);
- if (result.good())
+ if (segmentation)
{
- segmentation->m_Frames = frames;
+ result = segmentation->readWithoutPixelData(dset);
+ if (result.good())
+ {
+ segmentation->m_Frames = frames;
+ // We don't check the transfer syntax in the input files,
+ // so even all files had the same transfer syntax, we always
+ // set it to EXS_Unknown.
+ segmentation->m_inputXfer = EXS_Unknown;
+ }
+ }
+ else
+ {
+ result = EC_MemoryExhausted;
}
- }
- else
- {
- result = EC_MemoryExhausted;
}
}
if (result.bad())
const ContentIdentificationMacro& contentIdentification)
{
- OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification);
+ OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification, 8);
if (result.bad())
return result;
return result;
}
+
+OFCondition DcmSegmentation::createLabelmapSegmentation(DcmSegmentation *&segmentation,
+ const Uint16 rows,
+ const Uint16 columns,
+ const IODGeneralEquipmentModule::EquipmentInfo &equipmentInfo,
+ const ContentIdentificationMacro &contentIdentification,
+ const OFBool use16Bit,
+ const DcmSegTypes::E_SegmentationLabelmapColorModel colorModel)
+{
+ if (colorModel == DcmSegTypes::SLCM_UNKNOWN)
+ {
+ DCMSEG_ERROR("Cannot create labelmap segmentation: Color model not set");
+ return EC_IllegalParameter;
+ }
+
+ OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification, use16Bit ? 16 : 8);
+ if (result.bad())
+ return result;
+
+ segmentation->m_SegmentationType = DcmSegTypes::ST_LABELMAP;
+ segmentation->m_16BitPixelData = use16Bit;
+ segmentation->m_LabelmapColorModel = colorModel;
+ return result;
+}
+
OFCondition DcmSegmentation::createFractionalSegmentation(DcmSegmentation*& segmentation,
const Uint16 rows,
const Uint16 columns,
const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo,
const ContentIdentificationMacro& contentIdentification)
{
- OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification);
+ OFCondition result = createCommon(segmentation, rows, columns, equipmentInfo, contentIdentification, 8);
if (result.bad())
return result;
const Uint16 rows,
const Uint16 columns,
const IODGeneralEquipmentModule::EquipmentInfo& equipmentInfo,
- const ContentIdentificationMacro& contentIdentification)
+ const ContentIdentificationMacro& contentIdentification,
+ const Uint16 bitsAllocated)
{
if ((rows == 0) || (columns == 0))
{
return EC_IllegalParameter;
}
- segmentation = new DcmSegmentation();
+ OFCondition result = createRequiredBitDepth(bitsAllocated, segmentation);
if (segmentation == NULL)
return EC_MemoryExhausted;
segmentation->getImagePixel().setRows(rows);
segmentation->getImagePixel().setColumns(columns);
- OFCondition result = segmentation->setContentIdentification(contentIdentification);
+ DCMSEG_DEBUG("Setting segmentation content identification");
+ result = segmentation->setContentIdentification(contentIdentification);
if (result.good())
{
- OFString tempstr;
- contentIdentification.getInstanceNumber(tempstr);
- result = segmentation->getGeneralImage().setInstanceNumber(tempstr);
- if (result.bad())
- {
- delete segmentation;
- segmentation = NULL;
- return EC_InvalidValue;
- }
-
DcmIODUtil::setContentDateAndTimeNow(segmentation->getGeneralImage());
+ DCMSEG_DEBUG("Setting segmentation equipment information");
result = segmentation->setEquipmentInfo(equipmentInfo, OFTrue /* check */);
}
return result;
}
+OFCondition DcmSegmentation::createRequiredBitDepth(const Uint16 bitsAllocated, DcmSegmentation*& seg)
+{
+ OFCondition result;
+ seg = NULL;
+ if (bitsAllocated == 16)
+ {
+ seg = new DcmSegmentation(OFin_place<IODImagePixelModule<Uint16> >);
+ }
+ else if ( (bitsAllocated == 8) || (bitsAllocated == 1) )
+ {
+ seg = new DcmSegmentation(OFin_place<IODImagePixelModule<Uint8> >);
+ }
+ else
+ {
+ DCMSEG_ERROR("Cannot read segmentation object: Bits Allocated is neither 8 nor 16");
+ result = IOD_EC_InvalidPixelData;
+ }
+ if (result.good() && (seg == NULL))
+ {
+ result = EC_MemoryExhausted;
+ }
+ return result;
+
+}
+
+OFCondition DcmSegmentation::createRequiredBitDepth(DcmItem& item, DcmSegmentation*& seg)
+{
+ Uint16 bitsAllocated = 0;
+ OFCondition result = item.findAndGetUint16(DCM_BitsAllocated, bitsAllocated);
+ if (result.bad())
+ {
+ DCMSEG_ERROR("Cannot read Bits Allocated from dataset: " << result.text());
+ return result;
+ }
+ return createRequiredBitDepth(bitsAllocated, seg);
+}
+
+
FGDerivationImage*
DcmSegmentation::createDerivationImageFG(const OFVector<ImageSOPInstanceReferenceMacro>& derivationImages,
const OFString& derivationDescription)
OFCondition DcmSegmentation::readWithoutPixelData(DcmItem& dataset)
{
OFString sopClass;
- if (DcmIODUtil::checkSOPClass(&dataset, UID_SegmentationStorage, sopClass).bad())
+ if (DcmIODUtil::checkSOPClass(&dataset, UID_SegmentationStorage, sopClass).bad()
+ && DcmIODUtil::checkSOPClass(&dataset, UID_LabelMapSegmentationStorage, sopClass).bad())
{
DCMSEG_ERROR("Given file does not seem to be a segmentation storage object since SOP class is: " << sopClass);
return IOD_EC_WrongSOPClass;
}
// Read attributes in base classes
- DcmSegmentation::IODImage::read(dataset);
+ OFCondition result = DcmSegmentation::IODImage::read(dataset);
+ if (result.bad())
+ DCMSEG_WARN("Problem with reading Image Pixel attributes: " << result.text() << " (ignoring)");
// Read Segmentation Series Module
m_SegmentationSeries.read(dataset);
readSegments(dataset);
- readSegmentationFractionalType(dataset);
+ if (m_SegmentationType == DcmSegTypes::ST_FRACTIONAL)
+ readSegmentationFractionalType(dataset);
m_ContentIdentificationMacro.read(dataset);
+ // Read Photometric Interpretation and check whether it fits the segmentation type
+ OFString colorModel;
+ if (dataset.findAndGetOFString(DCM_PhotometricInterpretation, colorModel).good() && (colorModel == "PALETTE COLOR"))
+ {
+ // For palette, read Palette Color LUT Module and ICC Profile Module
+ m_PaletteColorLUTModule.read(dataset);
+ m_ICCProfileModule.read(dataset);
+ }
+ checkColorModel(colorModel);
+
// Read specific segmentation elements
DcmIODUtil::getAndCheckElementFromDataset(
- dataset, m_MaximumFractionalValue, getRules()->getByTag(DCM_MaximumFractionalValue));
+ dataset, m_MaximumFractionalValue, DcmSegmentation::IODImage::getRules()->getByTag(DCM_MaximumFractionalValue));
return EC_Normal;
}
return m_FGInterface.getCheckOnWrite();
}
+void DcmSegmentation::setValueCheckOnWrite(const OFBool doCheck)
+{
+ m_SegmentationSeries.setValueCheckOnWrite(doCheck);
+ m_EnhancedGeneralEquipmentModule.setValueCheckOnWrite(doCheck);
+ m_PaletteColorLUTModule.setValueCheckOnWrite(doCheck);
+ m_DimensionModule.setValueCheckOnWrite(doCheck);
+ m_ICCProfileModule.setValueCheckOnWrite(doCheck);
+ DcmSegmentation::IODImage::setValueCheckOnWrite(doCheck);
+}
+
void DcmSegmentation::setCheckDimensionsOnWrite(const OFBool doCheck)
{
m_DimensionModule.setCheckOnWrite(doCheck);
return m_DimensionModule.getCheckOnWrite();
}
+E_TransferSyntax DcmSegmentation::getInputTransferSyntax() const
+{
+ return m_inputXfer;
+}
+
OFCondition DcmSegmentation::writeWithSeparatePixelData(DcmItem& dataset, Uint8*& pixData, size_t& pixDataLength)
{
// FGInterface::write() will know whether it has to check FG structure
OFCondition result;
// -- Set constant default values written by external modules --
- getGeneralImage().setLossyImageCompression("00");
- getGeneralImage().setImageType(m_ImageType);
- getSOPCommon().setSOPClassUID(UID_SegmentationStorage);
+ DcmSegmentation::IODImage::getGeneralImage().setLossyImageCompression("00");
+ DcmSegmentation::IODImage::getGeneralImage().setImageType(m_ImageType);
+ // Set Instance Number if not set
+ OFString InstanceNumber;
+ getData()->findAndGetOFString(DCM_InstanceNumber, InstanceNumber);
+ if (InstanceNumber.empty())
+ {
+ DcmSegmentation::IODImage::getGeneralImage().setInstanceNumber("1");
+ }
+
+ // Set SOP Class UID based on segmentation type
+ setSOPClassUIDBasedOnSegmentationType();
+
+ // -- Extra Study level data --
+
+ // Enhanced Equipment Module
+ if (result.good())
+ result = m_EnhancedGeneralEquipmentModule.write(dataset);
+
+ // -- Extra Series level data --
+
+ // Write segmentation-specific series level attribute (Segmentation Series Module)
+ if (result.good())
+ result = m_SegmentationSeries.write(dataset);
+
+ // -- Extra Image level data --
+
+ // Write Multi-Frame Functional Groups Module
+ if (result.good())
+ result = writeMultiFrameFunctionalGroupsModule(dataset);
+
+ // Write Multi-Frame Dimension Module
+ if (result.good())
+ result = writeMultiFrameDimensionModule(dataset);
+
+ // Write Palette Color Lookup Table Module and ICC Profile Module
+ if (result.good())
+ {
+ if (m_LabelmapColorModel == DcmSegTypes::SLCM_PALETTE)
+ {
+ result = m_PaletteColorLUTModule.write(dataset);
+ if (result.good())
+ {
+ result = m_ICCProfileModule.write(dataset);
+ }
+ }
+ }
+
+ // Write segmentation image module and image pixel module
+ if (result.good())
+ result = writeSegmentationImageModule(dataset);
+
+ // -- Write common multi frame image IOD attributes --
+
+ // Patient Module
+ // General Study Module
+ // General Series Module
+ // Frame of Reference Module
+ // General Equipment Module
+ // General Image Module
+ // Multi-frame Functional Groups Module (except functional groups itself)
+ // SOP Common Module
+ // Common Instance Reference Module
+ if (result.good())
+ result = DcmSegmentation::IODImage::write(dataset);
+
+ // Write frame pixel data
+ if (result.good())
+ {
+ Uint32 numFrames = DcmIODUtil::limitMaxFrames(
+ m_Frames.size(), "More than 2147483647 frames provided, will only write 2147483647");
+ Uint16 rows, cols, bytesPerPixel;
+ rows = cols = bytesPerPixel = 0;
+ DcmSegmentation::getImagePixel().getRows(rows);
+ DcmSegmentation::getImagePixel().getColumns(cols);
+ DcmSegmentation::getImagePixel().getBitsAllocated(bytesPerPixel);
+ if (bytesPerPixel >= 8) // 8 or 16
+ {
+ bytesPerPixel = bytesPerPixel / 8;
+ }
+ result = getTotalBytesRequired(rows, cols, bytesPerPixel, numFrames, pixDataLength);
+ if (result.bad())
+ return result;
+
+ pixData = new Uint8[pixDataLength];
+ if (!pixData)
+ return EC_MemoryExhausted;
+
+ switch (m_SegmentationType)
+ {
+ case DcmSegTypes::ST_BINARY:
+ result = writeBinaryFrames(pixData, rows, cols, pixDataLength);
+ break;
+ case DcmSegTypes::ST_FRACTIONAL:
+ case DcmSegTypes::ST_LABELMAP:
+ result = writeByteBasedFrames(pixData);
+ break;
+ default:
+ result = SG_EC_UnknownSegmentationType;
+ }
+ if (result.bad())
+ {
+ delete[] pixData;
+ }
+ }
+
+ return result;
+}
+
+OFCondition DcmSegmentation::writeWithSeparatePixelData(DcmItem& dataset, Uint16*& pixData, size_t& numPixelDataBytes)
+{
+ // FGInterface::write() will know whether it has to check FG structure
+ // so we do not need to check FG structure here (OFFalse).
+ if (!check(OFFalse))
+ {
+ return IOD_EC_InvalidObject;
+ }
+
+ OFCondition result;
+
+ // -- Set constant default values written by external modules --
+
+ DcmSegmentation::IODImage::getGeneralImage().setLossyImageCompression("00");
+ // Labelmap segmentations have a different SOP Class UID
+ DcmSegmentation::IODImage::getGeneralImage().setImageType(m_ImageType);
+
+ // Set SOP Class UID based on segmentation type
+ setSOPClassUIDBasedOnSegmentationType();
// -- Extra Study level data --
if (result.good())
result = writeMultiFrameDimensionModule(dataset);
+ // Write Palette Color Lookup Table Module and ICC Profile Module
+ if (result.good())
+ {
+ if (m_LabelmapColorModel == DcmSegTypes::SLCM_PALETTE)
+ {
+ result = m_PaletteColorLUTModule.write(dataset);
+ if (result.good())
+ {
+ result = m_ICCProfileModule.write(dataset);
+ }
+ }
+ }
+
// Write segmentation image module and image pixel module
if (result.good())
result = writeSegmentationImageModule(dataset);
{
Uint32 numFrames = DcmIODUtil::limitMaxFrames(
m_Frames.size(), "More than 2147483647 frames provided, will only write 2147483647");
- Uint16 rows, cols;
- rows = cols = 0;
+ Uint16 rows, cols, bytesPerPixel;
+ rows = cols = bytesPerPixel = 0;
getImagePixel().getRows(rows);
getImagePixel().getColumns(cols);
- result = getTotalBytesRequired(rows, cols, numFrames, pixDataLength);
+ getImagePixel().getBitsAllocated(bytesPerPixel);
+ if (bytesPerPixel >= 8) // 8 or 16
+ {
+ bytesPerPixel = bytesPerPixel / 8;
+ }
+ result = getTotalBytesRequired(rows, cols, bytesPerPixel, numFrames, numPixelDataBytes);
if (result.bad())
return result;
- pixData = new Uint8[pixDataLength];
+ pixData = new Uint16[numPixelDataBytes / 2]; // 16 bit data
if (!pixData)
return EC_MemoryExhausted;
- if (m_SegmentationType == DcmSegTypes::ST_BINARY)
- result = writeBinaryFrames(pixData, rows, cols, pixDataLength);
- else if (m_SegmentationType == DcmSegTypes::ST_FRACTIONAL)
- result = writeFractionalFrames(pixData);
- else
- result = SG_EC_UnknownSegmentationType;
+ switch (m_SegmentationType)
+ {
+ case DcmSegTypes::ST_BINARY:
+ DCMSEG_ERROR("Binary segmentations must be instantiated with 8 bit pixel data (Uint8)");
+ result = IOD_EC_InvalidPixelData;
+ break;
+ case DcmSegTypes::ST_FRACTIONAL:
+ DCMSEG_ERROR("Fractional segmentations must be instantiated with 8 bit pixel data (Uint8)");
+ result = IOD_EC_InvalidPixelData;
+ break;
+ case DcmSegTypes::ST_LABELMAP:
+ result = writeByteBasedFrames(pixData);
+ break;
+ default:
+ result = SG_EC_UnknownSegmentationType;
+ }
if (result.bad())
{
delete[] pixData;
return m_FGInterface.getNumberOfFrames();
}
+OFBool DcmSegmentation::has16BitPixelData() const
+{
+ return this->m_16BitPixelData;
+}
+
+Uint16 DcmSegmentation::getRows()
+{
+ Uint16 rows = 0;
+ DcmSegmentation::getImagePixel().getRows(rows);
+ return rows;
+}
+
+Uint16 DcmSegmentation::getColumns()
+{
+ Uint16 cols = 0;
+ DcmSegmentation::getImagePixel().getColumns(cols);
+ return cols;
+}
+
size_t DcmSegmentation::getNumberOfSegments()
{
return m_Segments.size();
OFCondition DcmSegmentation::addSegment(DcmSegment* seg, Uint16& segmentNumber)
{
- segmentNumber = 0;
if (seg == NULL)
return EC_IllegalParameter;
{
return SG_EC_MaxSegmentsReached;
}
-
- // Casting is safe since we made sure number of segments fits into 16 bit
- segmentNumber = OFstatic_cast(Uint16, m_Segments.size() + 1);
- m_Segments.push_back(seg);
- return EC_Normal;
-}
-
-OFCondition DcmSegmentation::addFrame(Uint8* pixData)
-{
- if (m_Frames.size() >= DCM_SEG_MAX_FRAMES)
- return SG_EC_MaxFramesReached;
-
- OFCondition result;
- Uint16 rows = 0;
- Uint16 cols = 0;
- if (getImagePixel().getRows(rows).good() && getImagePixel().getColumns(cols).good())
+ // For labelmaps, use the given segment number
+ if (m_SegmentationType == DcmSegTypes::ST_LABELMAP)
{
- DcmIODTypes::Frame* frame = NULL;
- if (m_SegmentationType == DcmSegTypes::ST_BINARY)
- {
- frame = DcmSegUtils::packBinaryFrame(pixData, rows, cols);
- if (!frame)
- {
- result = IOD_EC_CannotInsertFrame;
- }
- // with debug logging enabled, print out the binary frame
- if (DCM_dcmsegLogger.isEnabledFor(dcmtk::log4cplus::DEBUG_LOG_LEVEL))
- {
- DCMSEG_DEBUG("Added binary segmentation frame:");
- DcmSegUtils::debugDumpBin(frame->pixData, frame->length, "Binary frame", OFTrue);
- }
- }
- else // fractional
- {
- frame = new DcmIODTypes::Frame();
- if (frame)
- {
- frame->length = rows * cols;
- frame->pixData = new Uint8[frame->length];
- if (frame->pixData)
- {
- memcpy(frame->pixData, pixData, frame->length);
- }
- else
- {
- delete frame;
- result = EC_MemoryExhausted;
- }
- }
- else
- result = EC_MemoryExhausted;
- }
- if (result.good())
- {
- m_Frames.push_back(frame);
- }
+ m_Segments.insert(OFMake_pair(segmentNumber, seg));
+ return EC_Normal;
}
- else
+ // For binary/fractional, start with 1 if no segment exists
+ if (m_Segments.empty())
{
- DCMSEG_ERROR("Cannot add frame since rows and/or columns are unknown");
- result = IOD_EC_CannotInsertFrame;
+ segmentNumber = 1;
+ m_Segments.insert(OFMake_pair(segmentNumber, seg));
+ return EC_Normal;
}
- return result;
+ // Use next free segment number and insert
+ // (i.e. get the highest segment number and increment by 1).
+ OFMap<Uint16, DcmSegment*>::iterator it = m_Segments.end();
+ it--;
+ segmentNumber = it->first + 1;
+ m_Segments.insert(OFMake_pair(segmentNumber, seg));
+ return EC_Normal;
}
+
SOPInstanceReferenceMacro& DcmSegmentation::getReferencedPPS()
{
- return getSeries().getReferencedPPS();
+ return DcmSegmentation::IODImage::getSeries().getReferencedPPS();
}
-const DcmIODTypes::Frame* DcmSegmentation::getFrame(const size_t& frameNo)
+const DcmIODTypes::FrameBase* DcmSegmentation::getFrame(const size_t& frameNo)
{
if (frameNo > m_Frames.size() - 1)
{
return m_FGInterface.addShared(group);
}
-OFCondition
-DcmSegmentation::addFrame(Uint8* pixData, const Uint16 segmentNumber, const OFVector<FGBase*>& perFrameInformation)
-{
- if (m_Frames.size() >= DCM_SEG_MAX_FRAMES)
- return SG_EC_MaxFramesReached;
-
- Uint32 frameNo = OFstatic_cast(Uint32, m_Frames.size()); // will be the index of the frame (counted from 0)
- OFCondition result;
-
- // Check input parameters
- if (pixData == NULL)
- {
- DCMSEG_ERROR("No pixel data provided or zero length");
- result = EC_IllegalParameter;
- }
- if (segmentNumber > m_Segments.size())
- {
- DCMSEG_ERROR("Cannot add frame: Segment with given number " << segmentNumber << " does not exist");
- result = SG_EC_NoSuchSegment;
- }
- if (result.bad())
- return result;
-
- OFVector<FGBase*>::const_iterator it = perFrameInformation.begin();
- while (it != perFrameInformation.end())
- {
- result = (*it)->check();
- if (result.bad())
- {
- DCMSEG_ERROR("Could not add new frame since functional group of type: "
- << (*it)->getType() << " is invalid: " << result.text());
- break;
- }
- result = m_FGInterface.addPerFrame(frameNo, *(*it));
- if (result.bad())
- {
- DCMSEG_ERROR("Could not add new frame since functional group of type " << (*it)->getType() << ": "
- << result.text());
- break;
- }
- it++;
- }
-
- // Now also add Segmentation Functional Group
- if (result.good())
- {
- FGSegmentation seg;
- result = seg.setReferencedSegmentNumber(segmentNumber);
- if (result.good())
- {
- result = m_FGInterface.addPerFrame(frameNo, seg);
- }
- else
- {
- DCMSEG_ERROR("Could not add new frame, invalid segment number " << segmentNumber << ": " << result.text());
- }
- }
-
- // Insert pixel data
- if (result.good())
- {
- result = addFrame(pixData);
- }
-
- // Cleanup any per-frame groups that might have been inserted and return
- if (result.bad())
- {
- for (OFVector<FGBase*>::const_iterator it2 = perFrameInformation.begin(); it2 != perFrameInformation.end();
- it2++)
- {
- m_FGInterface.deletePerFrame(frameNo, (*it2)->getType());
- }
- }
-
- return result;
-}
-
ContentIdentificationMacro& DcmSegmentation::getContentIdentification()
{
return m_ContentIdentificationMacro;
return m_DimensionModule;
}
+IODPaletteColorLUTModule& DcmSegmentation::getPaletteColorLUT()
+{
+ return m_PaletteColorLUTModule;
+}
+
+IODICCProfileModule& DcmSegmentation::getICCProfile()
+{
+ return m_ICCProfileModule;
+}
+
OFCondition
DcmSegmentation::setLossyImageCompressionFlag(const OFString& ratios, const OFString& methods, const OFBool checkValues)
{
- OFCondition result = getGeneralImage().setLossyImageCompression("01");
+ OFCondition result = DcmSegmentation::IODImage::getGeneralImage().setLossyImageCompression("01");
if (result.good() || !checkValues)
- result = getGeneralImage().setLossyImageCompressionMethod(methods);
+ result = DcmSegmentation::IODImage::getGeneralImage().setLossyImageCompressionMethod(methods);
if (result.good() || !checkValues)
- result = getGeneralImage().setLossyImageCompressionRatio(ratios);
+ result = DcmSegmentation::IODImage::getGeneralImage().setLossyImageCompressionRatio(ratios);
if (checkValues)
return result;
#endif
)
{
- DcmXfer ts(writeXfer);
+ if ((writeXfer == EXS_RLELossless) && (m_SegmentationType != DcmSegTypes::ST_LABELMAP))
+ {
+ DcmXfer ts(writeXfer);
#ifdef WITH_ZLIB
- DCMSEG_ERROR("Cannot write transfer syntax: " << ts.getXferName()
+ DCMSEG_ERROR("Cannot write transfer syntax: " << ts.getXferName()
<< ": Can only write uncompressed or Deflated)");
#else
- if (writeXfer == EXS_DeflatedLittleEndianExplicit)
- {
- DCMSEG_ERROR("Cannot write transfer syntax: "
- << ts.getXferName() << ": Deflate (ZLIB) support disabled, can only write uncompressed");
- }
+ if (writeXfer == EXS_DeflatedLittleEndianExplicit)
+ {
+ DCMSEG_ERROR("Cannot write transfer syntax: "
+ << ts.getXferName() << ": Deflate (ZLIB) support disabled");
+ }
#endif
- return EC_CannotChangeRepresentation;
+ return EC_CannotChangeRepresentation;
+ }
}
DcmFileFormat dcmff;
OFCondition result = writeDataset(*(dcmff.getDataset()));
if (result.good())
{
- result = dcmff.saveFile(filename.c_str(), writeXfer);
+ if (dcmff.chooseRepresentation(writeXfer, NULL).good() && dcmff.getDataset()->canWriteXfer(writeXfer))
+ {
+ result = dcmff.saveFile(filename.c_str(), writeXfer, EET_ExplicitLength);
+ }
+ else
+ {
+ DcmXfer ts(writeXfer);
+ DCMSEG_ERROR("Cannot write transfer syntax: " << ts.getXferName());
+ result = EC_CannotChangeRepresentation;
+ }
}
if (result.bad())
{
/* -- Getter for DICOM attributes -- */
-DcmSegment* DcmSegmentation::getSegment(const size_t segmentNumber)
+DcmSegment* DcmSegmentation::getSegment(const Uint16 segmentNumber)
{
// check for invalid index
- if ((segmentNumber == 0) || (segmentNumber > m_Segments.size()))
+ if ( (m_SegmentationType != DcmSegTypes::ST_LABELMAP) && (segmentNumber == 0) )
+ {
+ DCMSEG_ERROR("Cannot get segment 0: No such Segment Number allowed segmentation if segmentation is of type " << DcmSegTypes::segtype2OFString(m_SegmentationType));
+ return NULL;
+ }
+ OFMap<Uint16, DcmSegment*>::iterator it = m_Segments.find(segmentNumber);
+ if (it == m_Segments.end())
{
return NULL;
}
- // logical segment numbering starts with 1, so subtract 1 for vector index
- return m_Segments[segmentNumber - 1];
+ return it->second;
}
OFBool DcmSegmentation::getSegmentNumber(const DcmSegment* segment, size_t& segmentNumber)
{
- segmentNumber = 0;
- size_t max = m_Segments.size();
- for (size_t count = 0; count < max; count++)
+ if (segment == NULL)
+ return OFFalse;
+
+ OFMap<Uint16, DcmSegment*>::iterator it = m_Segments.begin();
+ while (it != m_Segments.end())
{
- if (m_Segments.at(count) == segment)
+ if (it->second == segment)
{
- segmentNumber = OFstatic_cast(Uint16, count + 1);
+ segmentNumber = it->first;
return OFTrue;
}
+ it++;
}
- // not found
return OFFalse;
}
+const OFMap<Uint16, DcmSegment*>& DcmSegmentation::getSegments()
+{
+ return m_Segments;
+}
+
OFCondition DcmSegmentation::getModality(OFString& value, const long signed int pos) const
{
(void)pos;
OFCondition DcmSegmentation::writeSegments(DcmItem& item)
{
OFCondition result;
+ // writeSubSequence cannot handle a map, copy to vector instead and use that for this purpose
+ OFVector<DcmSegment*> segments;
+ OFMap<Uint16, DcmSegment*>::iterator it = m_Segments.begin();
+ while (it != m_Segments.end())
+ {
+ segments.push_back(it->second);
+ it++;
+ }
DcmIODUtil::writeSubSequence<OFVector<DcmSegment*> >(
- result, DCM_SegmentSequence, m_Segments, item, "1-n", "1", "SegmentationImageModule");
+ result, DCM_SegmentSequence, segments, item, "1-n", "1", "SegmentationImageModule");
return result;
}
OFCondition DcmSegmentation::readSegments(DcmItem& item)
{
- return DcmIODUtil::readSubSequence<OFVector<DcmSegment*> >(
- item, DCM_SegmentSequence, m_Segments, "1-n", "1", "SegmentationImageModule");
+ // readSubSequence cannot handle a map, read into vector instead and fill into map afterwards
+ OFVector<DcmSegment*> segments;
+
+ OFCondition result = DcmIODUtil::readSubSequence<OFVector<DcmSegment*> >(
+ item, DCM_SegmentSequence, segments, "1-n", "1", "SegmentationImageModule");
+ if (result.good())
+ {
+ for (size_t count = 0; count < segments.size(); count++)
+ {
+ if (result.good())
+ {
+ if (m_Segments.insert(OFMake_pair(segments[count]->getSegmentNumberRead(), segments[count])).second
+ == false)
+ {
+ DCMSEG_ERROR("Cannot insert segment " << segments[count]->getSegmentNumberRead()
+ << " since it already exists");
+ result = EC_IllegalCall;
+ break;
+ }
+ }
+ else
+ {
+ DCMSEG_ERROR("Cannot read segment number for segment " << count << ": " << result.text());
+ result = EC_IllegalCall;
+ break;
+ }
+ }
+ }
+
+ return result;
}
OFCondition DcmSegmentation::readFrames(DcmItem& dataset)
DcmElement* pixelData = NULL;
if (dataset.findAndGetElement(DCM_PixelData, pixelData).bad())
return IOD_EC_InvalidPixelData;
- if (!checkPixDataLength(pixelData, rows, cols, numberOfFrames))
+ Uint16 bytesPerPixel = (allocated >= 8) ? allocated / 8 : 1;
+ if (!checkPixDataLength(pixelData, rows, cols, bytesPerPixel, numberOfFrames))
return IOD_EC_InvalidPixelData;
+ if (bytesPerPixel == 2)
+ {
+ m_16BitPixelData = OFTrue;
+ }
/* Get pixel data values */
- Uint8* pixels = NULL;
- result = pixelData->getUint8Array(pixels);
+ size_t pixelsPerFrame = OFstatic_cast(size_t, rows) * cols;
+ result = readPixelData(pixelData, numberOfFrames, pixelsPerFrame, allocated);
+ return result;
+}
+
+OFCondition DcmSegmentation::readPixelData(DcmElement* pixelData, const size_t numFrames, const size_t pixelsPerFrame, const Uint16 bitsAlloc)
+{
+ Uint8* pixels8 = NULL;
+ Uint16* pixels16 = NULL;
+ OFCondition result;
+ if (( bitsAlloc == 1) || (bitsAlloc == 8))
+ {
+ result = pixelData->getUint8Array(pixels8);
+ }
+ else if (bitsAlloc == 16)
+ {
+ result = pixelData->getUint16Array(pixels16);
+ }
+ else
+ {
+ DCMSEG_ERROR("Cannot read pixel data: Bits Allocated is neither 1, 8 nor 16");
+ return IOD_EC_InvalidPixelData;
+ }
if (result.bad())
{
DCMSEG_ERROR("Cannot read pixel data");
return result;
}
-
/* Read all frames into dedicated data structure */
- size_t pixelsPerFrame = OFstatic_cast(size_t, rows) * cols;
- if (m_SegmentationType == DcmSegTypes::ST_BINARY)
- {
- result = DcmIODUtil::extractBinaryFrames(pixels, numberOfFrames, pixelsPerFrame, m_Frames);
- if (result.bad())
- {
- return result;
- }
- // with debug logging enabled, print out the binary frames
- if (DCM_dcmsegLogger.isEnabledFor(dcmtk::log4cplus::DEBUG_LOG_LEVEL))
- {
- DCMSEG_DEBUG("Extracted binary segmentation frame:");
- for (size_t count = 0; count < m_Frames.size(); count++)
- {
- DCMSEG_DEBUG("Frame " << count << ":");
- DcmIODTypes::Frame* frame = m_Frames[count];
- DcmSegUtils::debugDumpBin(frame->pixData, frame->length, "Binary frame", OFTrue);
- }
- }
- }
- else if (m_SegmentationType == DcmSegTypes::ST_FRACTIONAL)
+ switch (m_SegmentationType)
{
- for (size_t count = 0; count < numberOfFrames; count++)
- {
- DcmIODTypes::Frame* frame = new DcmIODTypes::Frame();
- if (!frame)
- return EC_MemoryExhausted;
- frame->length = pixelsPerFrame;
- frame->pixData = new Uint8[pixelsPerFrame];
- if (!frame->pixData)
+ case DcmSegTypes::ST_BINARY:
+ result = DcmIODUtil::extractBinaryFrames(pixels8, numFrames, pixelsPerFrame, m_Frames);
+ break;
+ case DcmSegTypes::ST_FRACTIONAL:
+ case DcmSegTypes::ST_LABELMAP:
+ for (size_t count = 0; count < numFrames; count++)
{
- delete frame;
- return EC_MemoryExhausted;
+ DcmIODTypes::FrameBase* frame = NULL;
+ if (bitsAlloc == 8)
+ {
+ frame = new DcmIODTypes::Frame<Uint8>(pixelsPerFrame);
+ }
+ else if (bitsAlloc == 16)
+ {
+ frame = new DcmIODTypes::Frame<Uint16>(pixelsPerFrame);
+ }
+ if (!frame || !frame->getPixelData())
+ {
+ delete frame;
+ result = EC_MemoryExhausted;
+ break;
+ }
+ if (bitsAlloc == 8)
+ {
+ memcpy(frame->getPixelData(), pixels8 + count * pixelsPerFrame, pixelsPerFrame);
+ }
+ else // 16
+ {
+ memcpy(frame->getPixelData(), pixels16 + count * pixelsPerFrame, frame->getLengthInBytes());
+ }
+ // print frame->pixData to cout
+ // frame->print();
+ m_Frames.push_back(frame);
}
- memcpy(frame->pixData, pixels + count * pixelsPerFrame, pixelsPerFrame);
- m_Frames.push_back(frame);
- }
+ break;
+ case DcmSegTypes::ST_UNKNOWN:
+ result = SG_EC_UnknownSegmentationType;
}
-
return result;
}
+
OFCondition DcmSegmentation::getAndCheckImagePixelAttributes(DcmItem& dataset,
Uint16& allocated,
Uint16& stored,
}
}
- Uint16 depth = 0;
- if (m_SegmentationType == DcmSegTypes::ST_BINARY)
- depth = 1;
- else
- depth = 8;
-
- if (allocated != depth)
+ switch (m_SegmentationType)
{
- DCMSEG_WARN("Bits Allocated is not set correctly ("
- << allocated << ", ignored), assuming value " << depth << " as required for "
- << DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects");
- allocated = depth;
+ case DcmSegTypes::ST_BINARY:
+ if (allocated != 1)
+ {
+ DCMSEG_WARN("Bits Allocated is not set correctly ("
+ << allocated << ", ignored), assuming value 1 as required for binary segmentation objects");
+ allocated = 1;
+ }
+ break;
+ case DcmSegTypes::ST_FRACTIONAL:
+ if (allocated != 8)
+ {
+ DCMSEG_WARN("Bits Allocated is not set correctly ("
+ << allocated
+ << ", ignored), assuming value 8 as required for fractional segmentation "
+ "objects");
+ allocated = 8;
+ }
+ break;
+ case DcmSegTypes::ST_LABELMAP:
+ if ((allocated != 8) && (allocated != 16))
+ {
+ DCMSEG_ERROR("Bits Allocated is not set correctly (" << allocated << ", giving up");
+ fail = OFTrue;
+ }
+ break;
+ case DcmSegTypes::ST_UNKNOWN:
+ fail = OFTrue;
+ break;
+ }
+ if (fail)
+ {
+ return EC_InvalidValue;
}
- if (stored != depth)
+ if (stored != allocated)
{
DCMSEG_WARN("Bits Stored is not set correctly ("
- << stored << ", ignored), assuming value " << depth << " as required for "
+ << stored << ", ignored), assuming value " << allocated << " as required for "
<< DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects");
- stored = depth;
+ stored = allocated;
+ }
+ if (m_SegmentationType == DcmSegTypes::ST_BINARY)
+ {
+ if (high != 0)
+ {
+ DCMSEG_WARN("High Bit is not set correctly ("
+ << high << ", ignored), assuming value 0 as required for binary segmentation objects");
+ high = 0;
+ }
}
- if (high != depth - 1)
+ else if (high != allocated - 1)
{
DCMSEG_WARN("High Bit is not set correctly ("
- << high << ", ignored), assuming value " << depth - 1 << " as required for "
+ << high << ", ignored), assuming value " << allocated - 1 << " as required for "
<< DcmSegTypes::segtype2OFString(m_SegmentationType) << " segmentation objects");
- high = depth - 1;
+ high = allocated - 1;
}
if (spp != 1)
{
<< pixelRep << ", ignored), assuming value 0 as required for segmentation objects");
pixelRep = 0;
}
- if (colorModel != "MONOCHROME2")
+ if ((colorModel != "MONOCHROME2")
+ && ((colorModel != "PALETTE COLOR") && (m_SegmentationType == DcmSegTypes::ST_LABELMAP)))
{
- DCMSEG_WARN("Photometric Interpretation is not set correctly (ignored), assuming value MONOCHROME2 as required "
- "for segmentation objects");
- colorModel = "MONOCHROME2";
+ DCMSEG_WARN("Photometric Interpretation is not set correctly (" << colorModel << "): Must be MONOCHROME2 or PALETTE COLOR (only Labelmap segmentations)");
+ fail = OFTrue;
}
if (rows == 0)
{
OFCondition DcmSegmentation::writeDataset(DcmItem& dataset)
{
- Uint8* pixData = NULL;
- size_t pixDataLength;
- OFCondition result = writeWithSeparatePixelData(dataset, pixData, pixDataLength);
+ Uint8* pixData8 = NULL;
+ Uint16* pixData16 = NULL;
+ size_t pixDataLength = 0;
+ OFCondition result;
+ if (has16BitPixelData())
+ {
+ result = writeWithSeparatePixelData(dataset, pixData16, pixDataLength);
+ }
+ else
+ {
+ result = writeWithSeparatePixelData(dataset, pixData8, pixDataLength);
+ }
if (result.good())
{
// Check whether pixel data length exceeds maximum number of bytes for uncompressed pixel data,
// enforced by length field of Pixel Data attribute VR OB/OW if written in explicit VR transfer syntax.
if (pixDataLength <= 4294967294UL)
{
- result
- = dataset.putAndInsertUint8Array(DCM_PixelData, pixData, OFstatic_cast(unsigned long, pixDataLength));
+ if (has16BitPixelData())
+ {
+ result = dataset.putAndInsertUint16Array(DCM_PixelData, pixData16, OFstatic_cast(unsigned long, pixDataLength / 2));
+ }
+ else
+ {
+ result = dataset.putAndInsertUint8Array(DCM_PixelData, pixData8, OFstatic_cast(unsigned long, pixDataLength));
+ }
}
else
{
result = FG_EC_PixelDataTooLarge;
}
- delete[] pixData;
+ delete[] pixData8;
+ delete[] pixData16;
}
return result;
}
OFCondition DcmSegmentation::writeConcatenation(ConcatenationCreator& cc)
{
- Uint8* pixData = NULL;
size_t pixDataLength = 0;
DcmItem* item = new DcmItem();
if (!item)
return EC_MemoryExhausted;
- OFCondition result = writeWithSeparatePixelData(*item, pixData, pixDataLength);
- if (result.good())
+ OFCondition result;
+ if (has16BitPixelData())
+ {
+ Uint16* pixData = NULL;
+ result = writeWithSeparatePixelData(*item, pixData, pixDataLength);
+ if (result.good())
+ {
+ result = cc.setCfgInput(item, pixData, pixDataLength, OFTrue /* transfer ownership */);
+ }
+ }
+ else
{
- result = cc.setCfgInput(item, pixData, pixDataLength, OFTrue /* transfer ownership */);
+ Uint8* pixData = NULL;
+ result = writeWithSeparatePixelData(*item, pixData, pixDataLength);
+ if (result.good())
+ {
+ result = cc.setCfgInput(item, pixData, pixDataLength, OFTrue /* transfer ownership */);
+ }
}
return result;
}
return m_DimensionModule.write(dataset);
}
-OFCondition DcmSegmentation::writeFractionalFrames(Uint8* pixData)
+template <typename T>
+OFCondition DcmSegmentation::writeByteBasedFrames(T* pixData)
{
- OFVector<DcmIODTypes::Frame*>::iterator it = m_Frames.begin();
+ Uint8 bytesPerPixel = sizeof(T);
+ typename OFVector<DcmIODTypes::FrameBase*>::iterator it = m_Frames.begin();
// Just copy bytes for each frame as is
for (size_t count = 0; it != m_Frames.end(); count++)
{
- memcpy(pixData + count * (*it)->length, (*it)->pixData, (*it)->length);
+ memcpy(pixData + count * (*it)->getLengthInBytes() / bytesPerPixel, (*it)->getPixelData(), (*it)->getLengthInBytes());
it++;
}
return EC_Normal;
dataset.putAndInsertOFStringArray(DCM_ImageType, "DERIVED\\PRIMARY");
OFCondition result = m_ContentIdentificationMacro.write(dataset);
+ OFString colorModel;
/* Write hardcoded values */
if (result.good())
- {
- getImagePixel().setSamplesPerPixel(1);
- getImagePixel().setPhotometricInterpretation("MONOCHROME2");
- getImagePixel().setPixelRepresentation(0);
+ { Uint16 rows, cols, bitsAlloc, bitsStored, highBit, pixelRep, samplesPixel;
+ rows = cols = bitsAlloc = bitsStored = highBit = pixelRep = samplesPixel = 0;
+ OFString photometricInterpretation;
+ samplesPixel = 1;
+
+ colorModel = determineColorModel();
+ pixelRep = 0;
/* Write Bits Allocated/Stored, High Bit, Segmentation Fractional Type,
* Segmentation Type, Maximum Fractional Value
{
case DcmSegTypes::ST_BINARY:
{
- getImagePixel().setBitsAllocated(1);
- getImagePixel().setBitsStored(1);
- getImagePixel().setHighBit(0);
+ bitsAlloc = 1;
+ bitsStored = 1;
+ highBit = 1;
dataset.putAndInsertOFStringArray(DCM_SegmentationType, "BINARY");
+ dataset.putAndInsertOFStringArray(DCM_SegmentsOverlap, "UNDEFINED");
break;
}
case DcmSegTypes::ST_FRACTIONAL:
+ case DcmSegTypes::ST_LABELMAP:
{
- getImagePixel().setBitsAllocated(8);
- getImagePixel().setBitsStored(8);
- getImagePixel().setHighBit(7);
- dataset.putAndInsertOFStringArray(DCM_SegmentationType, "FRACTIONAL");
- if (m_SegmentationFractionalType == DcmSegTypes::SFT_OCCUPANCY)
+ Uint8 numBits = 8;
+ if (has16BitPixelData())
{
- dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "OCCUPANCY");
+ numBits = 16;
+ }
+ bitsAlloc = bitsStored = numBits;
+ highBit = numBits -1;
+
+ if (m_SegmentationType == DcmSegTypes::ST_LABELMAP)
+ {
+ dataset.putAndInsertOFStringArray(DCM_SegmentationType, "LABELMAP");
+ dataset.putAndInsertOFStringArray(DCM_SegmentsOverlap, "NO");
}
else
{
- dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "PROBABILITY");
+ dataset.putAndInsertOFStringArray(DCM_SegmentationType, "FRACTIONAL");
+ dataset.putAndInsertOFStringArray(DCM_SegmentsOverlap, "UNDEFINED");
+ if (m_SegmentationFractionalType == DcmSegTypes::SFT_OCCUPANCY)
+ {
+ dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "OCCUPANCY");
+ }
+ else
+ {
+ dataset.putAndInsertOFStringArray(DCM_SegmentationFractionalType, "PROBABILITY");
+ }
+ // Maximum Fractional Value: Attribute is type 1C but "required if .. FRACTIONAL", i.e. write type 1
+ DcmIODUtil::copyElementToDataset(
+ result, dataset, m_MaximumFractionalValue, "1", "1", "SegmentationImageModule");
}
- // Maximum Fractional Value: Attribute is type 1C but "required if .. FRACTIONAL", i.e. write type 1
- DcmIODUtil::copyElementToDataset(
- result, dataset, m_MaximumFractionalValue, "1", "1", "SegmentationImageModule");
break;
}
case DcmSegTypes::ST_UNKNOWN:
break;
}
}
+ getImagePixel().getRows(rows);
+ getImagePixel().getColumns(cols);
+ if (bitsAlloc == 16)
+ {
+ result = SetImagePixelModuleVisitor(rows, cols,bitsAlloc, bitsStored, highBit, samplesPixel, colorModel)
+ (*OFget<IODImagePixelModule<Uint16> >(&getImagePixel()));
+ }
+ else
+ {
+ result = SetImagePixelModuleVisitor(rows, cols,bitsAlloc, bitsStored, highBit, samplesPixel, colorModel)
+ (*OFget<IODImagePixelModule<Uint8> >(&getImagePixel()));
+ }
+
}
/* Write segments */
OFVector<DcmItem*> segmentItems;
if (result.good())
{
- OFVector<DcmSegment*>::iterator it = m_Segments.begin();
+ OFMap<Uint16, DcmSegment*>::iterator it = m_Segments.begin();
dataset.findAndDeleteElement(DCM_SegmentSequence);
for (Uint16 itemCount = 0; (it != m_Segments.end()) && result.good(); itemCount++)
{
dataset.findOrCreateSequenceItem(DCM_SegmentSequence, segmentItem, itemCount);
if (segmentItem)
{
- result = (*it)->write(*segmentItem);
+ result = (*it).second->write(*segmentItem);
/* Insert segment number for the segment, starting from 1 and increasing monotonically. */
if (result.good())
{
- segmentItem->putAndInsertUint16(DCM_SegmentNumber, itemCount + 1);
+ segmentItem->putAndInsertUint16(DCM_SegmentNumber, (*it).first);
}
}
else
m_FG.clearData();
m_FGInterface.clear();
DcmIODUtil::freeContainer(m_Frames);
- DcmIODUtil::freeContainer(m_Segments);
+ DcmIODUtil::freeMap(m_Segments);
m_MaximumFractionalValue.clear();
m_SegmentationFractionalType = DcmSegTypes::SFT_UNKNOWN;
m_SegmentationType = DcmSegTypes::ST_UNKNOWN;
OFBool DcmSegmentation::checkPixDataLength(DcmElement* pixelData,
const Uint16 rows,
const Uint16 cols,
+ const Uint16 bytesPerPixel,
const Uint32& numberOfFrames)
{
// Get actual length of pixel data in bytes
// Find out how many bytes are needed
size_t bytesRequired = 0;
- OFCondition result = getTotalBytesRequired(rows, cols, numberOfFrames, bytesRequired);
+ OFCondition result = getTotalBytesRequired(rows, cols, bytesPerPixel, numberOfFrames, bytesRequired);
if (result.bad())
return OFFalse;
// Length found in Pixel Data element is always even
OFCondition DcmSegmentation::getTotalBytesRequired(const Uint16& rows,
const Uint16& cols,
+ const Uint16& bytesPerPixel,
const Uint32& numberOfFrames,
size_t& bytesRequired)
{
+ // Compute space needed for all frames, first assume 1 byte per pixel (we adapt later for binary segmentations)
+ // Rows * Cols = num pixels per frame
OFBool ok = OFStandard::safeMult(OFstatic_cast(size_t, rows), OFstatic_cast(size_t, cols), bytesRequired);
+ // Pixels per frame * num frames = total num pixels
if (ok)
OFStandard::safeMult(bytesRequired, OFstatic_cast(size_t, numberOfFrames), bytesRequired);
+ // In case of 16 bit pixel data, we need twice as much space
+ if (ok && (bytesPerPixel == 2))
+ OFStandard::safeMult(bytesRequired, OFstatic_cast(size_t, 2), bytesRequired);
if (!ok)
{
DCMSEG_ERROR("Cannot compute number of bytes required for Pixel Data since size_t type is too small");
return EC_TooManyBytesRequested;
}
- /* for binary, we only need one bit per pixel */
+ // Until this point we assumed bytes per pixel = 1. Now we need to adjust this
+ // for binary segmentation objects.with 1 bit per pixel.
size_t remainder = 0;
if (m_SegmentationType == DcmSegTypes::ST_BINARY)
{
return EC_Normal;
}
-OFCondition DcmSegmentation::loadFile(DcmFileFormat& dcmff, const OFString& filename, DcmDataset*& dset)
+OFCondition DcmSegmentation::loadFile(DcmFileFormat& dcmff, const OFString& filename, DcmDataset*& dset, const E_TransferSyntax xfer)
{
dset = NULL;
- OFCondition result = dcmff.loadFile(filename.c_str());
+ OFCondition result = dcmff.loadFile(filename.c_str(), xfer);
if (result.bad())
{
DCMSEG_ERROR("Could not load file " << filename << ": " << result.text());
return result;
}
+
OFCondition DcmSegmentation::readSegmentationFractionalType(DcmItem& item)
{
m_SegmentationFractionalType = DcmSegTypes::SFT_UNKNOWN;
}
DcmCodeString element(DCM_SegmentationFractionalType);
OFCondition result = DcmIODUtil::getAndCheckElementFromDataset(
- item, element, getRules()->getByTag(DCM_SegmentationFractionalType));
+ item, element, DcmSegmentation::IODImage::getRules()->getByTag(DCM_SegmentationFractionalType));
OFString str;
if (result.good())
{
}
DcmCodeString element(DCM_SegmentationType);
- OFCondition result
- = DcmIODUtil::getAndCheckElementFromDataset(item, element, getRules()->getByTag(DCM_SegmentationType));
+ OFCondition result = DcmIODUtil::getAndCheckElementFromDataset(
+ item, element, DcmSegmentation::IODImage::getRules()->getByTag(DCM_SegmentationType));
OFString str;
if (result.good())
{
return result;
}
-// protected override of public base class function
-IODImagePixelModule<Uint8>& DcmSegmentation::getImagePixel()
-{
- return *OFget<IODImagePixelModule<Uint8> >(&DcmSegmentation::IODImage::getImagePixel());
-}
OFBool DcmSegmentation::check(const OFBool checkFGStructure)
{
DCMSEG_ERROR("Too many segments defined");
return OFFalse;
}
- if (m_Segments.size() > m_Frames.size())
+ // Check that all segments are referenced by at least one frame.
+ // This is not required for label maps, since frames are only indirectly (through their pixel values)
+ // referencing segments.
+ if ( (m_Segments.size() > m_Frames.size()) && (m_SegmentationType != DcmSegTypes::ST_LABELMAP) )
{
DCMSEG_ERROR("More segments than frames defined");
return OFFalse;
frameOfRefRequired = OFFalse;
}
OFString frameOfRef;
- getFrameOfReference().getFrameOfReferenceUID(frameOfRef);
+ DcmSegmentation::IODImage::getFrameOfReference().getFrameOfReferenceUID(frameOfRef);
if (frameOfRefRequired && frameOfRef.empty())
{
DCMSEG_ERROR("Frame of Reference UID is not set for Segmentation but is required");
return result;
}
+
+OFString DcmSegmentation::determineColorModel()
+{
+ OFString colorModel;
+ if (m_SegmentationType == DcmSegTypes::ST_LABELMAP)
+ {
+ colorModel = DcmSegTypes::labelmapColorModel2OFString(m_LabelmapColorModel, "MONOCHROME2");
+ }
+ else
+ {
+ colorModel = "MONOCHROME2";
+ }
+ return colorModel;
+}
+
+
+OFBool DcmSegmentation::checkColorModel(const OFString& photometricInterpretation)
+{
+ // For labelmaps, MONOCHROME2 and PALETTE is permitted
+ if (m_SegmentationType == DcmSegTypes::ST_LABELMAP)
+ {
+ if ((photometricInterpretation != "MONOCHROME2") && (photometricInterpretation != "PALETTE COLOR"))
+ {
+ DCMSEG_WARN("Photometric Interpretation is not set correctly (" << photometricInterpretation << "): Must be MONOCHROME2 or PALETTE COLOR for labelmaps");
+ m_LabelmapColorModel = DcmSegTypes::SLCM_UNKNOWN;
+ return OFFalse;
+ }
+ m_LabelmapColorModel = DcmSegTypes::OFString2LabelmapColorModel(photometricInterpretation);
+ }
+ else
+ {
+ if (photometricInterpretation != "MONOCHROME2")
+ {
+ DCMSEG_WARN("Photometric Interpretation is not set correctly (" << photometricInterpretation << "): Must be MONOCHROME2 for binary and fractional segmentations");
+ return OFFalse;
+ }
+ m_LabelmapColorModel = DcmSegTypes::SLCM_UNKNOWN; // not used for binary/fractional segmentations
+ }
+ // If we found PALETTE COLOR, check whether the Palette Color Lookup Table is present
+ if (m_LabelmapColorModel == DcmSegTypes::SLCM_PALETTE)
+ {
+ if (getPaletteColorLUT().numBits() == 0) // checks at least basic descriptor availability
+ {
+ DCMSEG_WARN("Photometric Interpretation is set to PALETTE COLOR but no or invalid Palette Color Lookup Table is present");
+ return OFFalse;
+ }
+ }
+ return OFTrue;
+}
+
+
+void DcmSegmentation::setSOPClassUIDBasedOnSegmentationType()
+{
+ switch (m_SegmentationType)
+ {
+ case DcmSegTypes::ST_LABELMAP:
+ DcmSegmentation::IODImage::getSOPCommon().setSOPClassUID(UID_LabelMapSegmentationStorage);
+ break;
+ case DcmSegTypes::ST_FRACTIONAL:
+ case DcmSegTypes::ST_BINARY:
+ DcmSegmentation::IODImage::getSOPCommon().setSOPClassUID(UID_SegmentationStorage);
+ break;
+ case DcmSegTypes::ST_UNKNOWN:
+ // Print warning if segmentation type is unknown
+ DCMSEG_WARN("Segmentation type is unknown, setting SOP Class UID to Segmentation Storage SOP Class");
+ DcmSegmentation::IODImage::getSOPCommon().setSOPClassUID(UID_SegmentationStorage);
+ break;
+ }
+}
+
+// Explicit instantiations
+template OFCondition DcmSegmentation::addFrame<Uint8>(Uint8*, const Uint16, const OFVector<FGBase*>&);
+template OFCondition DcmSegmentation::addFrame<Uint16>(Uint16*, const Uint16, const OFVector<FGBase*>&);
+template OFCondition DcmSegmentation::addFrame<Uint8>(Uint8* pixData);
+template OFCondition DcmSegmentation::addFrame<Uint16>(Uint16* pixData);
/*
*
- * Copyright (C) 2015-2022, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/config/osconfig.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmiod/iodutil.h"
#include "dcmtk/dcmseg/segdoc.h"
#include "dcmtk/dcmseg/segment.h"
#include "dcmtk/dcmseg/segtypes.h"
+#include "dcmtk/ofstd/oftypes.h"
OFCondition DcmSegment::create(DcmSegment*& segment,
const OFString& segmentLabel,
return result;
}
+
+
+DcmSegment* DcmSegment::clone(DcmSegmentation* seg)
+{
+ DcmSegment* newSegment = new DcmSegment(*this);
+ if (newSegment != NULL)
+ {
+ if (seg != NULL)
+ newSegment->m_SegmentationDoc = seg;
+ // else: keep reference to same DcmSegmentation document
+ }
+ return newSegment;
+}
+
+DcmSegment::DcmSegment(const DcmSegment& rhs)
+ : m_SegmentationDoc(rhs.m_SegmentationDoc)
+ , m_SegmentNumber(rhs.m_SegmentNumber)
+ , m_SegmentDescription(rhs.m_SegmentDescription)
+ , m_SegmentAlgorithmName(rhs.m_SegmentAlgorithmName)
+ , m_SegmentationAlgorithmIdentification(rhs.m_SegmentationAlgorithmIdentification)
+ , m_RecommendedDisplayGrayscaleValue(rhs.m_RecommendedDisplayGrayscaleValue)
+ , m_RecommendedDisplayCIELabValue(rhs.m_RecommendedDisplayCIELabValue)
+ , m_TrackingID(rhs.m_TrackingID)
+ , m_TrackingUID(rhs.m_TrackingUID)
+ , m_Rules(rhs.m_Rules->clone())
+{
+}
+
+DcmSegment& DcmSegment::operator=(const DcmSegment& rhs)
+{
+ if (this != &rhs)
+ {
+ m_SegmentationDoc = rhs.m_SegmentationDoc;
+ m_SegmentNumber = rhs.m_SegmentNumber;
+ m_SegmentDescription = rhs.m_SegmentDescription;
+ m_SegmentAlgorithmName = rhs.m_SegmentAlgorithmName;
+ m_SegmentationAlgorithmIdentification = rhs.m_SegmentationAlgorithmIdentification;
+ m_RecommendedDisplayGrayscaleValue = rhs.m_RecommendedDisplayGrayscaleValue;
+ m_RecommendedDisplayCIELabValue = rhs.m_RecommendedDisplayCIELabValue;
+ m_TrackingID = rhs.m_TrackingID;
+ m_TrackingUID = rhs.m_TrackingUID;
+ m_Rules.reset(rhs.m_Rules->clone());
+ }
+ return *this;
+}
+
OFCondition DcmSegment::read(DcmItem& item, const OFBool clearOldData)
{
if (clearOldData)
clearData();
m_SegmentDescription.read(item);
- DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentAlgorithmName, m_Rules.getByTag(DCM_SegmentAlgorithmName));
+ DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentAlgorithmName, m_Rules->getByTag(DCM_SegmentAlgorithmName));
DcmIODUtil::readSingleItem<AlgorithmIdentificationMacro>(item,
DCM_SegmentationAlgorithmIdentificationSequence,
"Segmentation Image Module");
DcmIODUtil::getAndCheckElementFromDataset(
- item, m_RecommendedDisplayGrayscaleValue, m_Rules.getByTag(DCM_RecommendedDisplayGrayscaleValue));
+ item, m_RecommendedDisplayGrayscaleValue, m_Rules->getByTag(DCM_RecommendedDisplayGrayscaleValue));
DcmIODUtil::getAndCheckElementFromDataset(
- item, m_RecommendedDisplayCIELabValue, m_Rules.getByTag(DCM_RecommendedDisplayCIELabValue));
- DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingID, m_Rules.getByTag(DCM_TrackingID));
- DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingUID, m_Rules.getByTag(DCM_TrackingUID));
+ item, m_RecommendedDisplayCIELabValue, m_Rules->getByTag(DCM_RecommendedDisplayCIELabValue));
+ DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingID, m_Rules->getByTag(DCM_TrackingID));
+ DcmIODUtil::getAndCheckElementFromDataset(item, m_TrackingUID, m_Rules->getByTag(DCM_TrackingUID));
+ DcmIODUtil::getAndCheckElementFromDataset(item, m_SegmentNumber, m_Rules->getByTag(DCM_SegmentNumber));
return EC_Normal;
}
{
OFCondition result;
result = m_SegmentDescription.write(item);
- DcmIODUtil::copyElementToDataset(result, item, m_SegmentAlgorithmName, m_Rules.getByTag(DCM_SegmentAlgorithmName));
+ DcmIODUtil::copyElementToDataset(result, item, m_SegmentAlgorithmName, m_Rules->getByTag(DCM_SegmentAlgorithmName));
if (result.good() && m_SegmentationAlgorithmIdentification.check(OFTrue /* quiet */).good())
{
}
DcmIODUtil::copyElementToDataset(
- result, item, m_RecommendedDisplayGrayscaleValue, m_Rules.getByTag(DCM_RecommendedDisplayGrayscaleValue));
+ result, item, m_RecommendedDisplayGrayscaleValue, m_Rules->getByTag(DCM_RecommendedDisplayGrayscaleValue));
DcmIODUtil::copyElementToDataset(
- result, item, m_RecommendedDisplayCIELabValue, m_Rules.getByTag(DCM_RecommendedDisplayCIELabValue));
- DcmIODUtil::copyElementToDataset(result, item, m_TrackingID, m_Rules.getByTag(DCM_TrackingID));
- DcmIODUtil::copyElementToDataset(result, item, m_TrackingUID, m_Rules.getByTag(DCM_TrackingUID));
+ result, item, m_RecommendedDisplayCIELabValue, m_Rules->getByTag(DCM_RecommendedDisplayCIELabValue));
+ DcmIODUtil::copyElementToDataset(result, item, m_TrackingID, m_Rules->getByTag(DCM_TrackingID));
+ DcmIODUtil::copyElementToDataset(result, item, m_TrackingUID, m_Rules->getByTag(DCM_TrackingUID));
+ m_SegmentNumber.putUint16(getSegmentNumber());
+ DcmIODUtil::copyElementToDataset(result, item, m_SegmentNumber, m_Rules->getByTag(DCM_SegmentNumber));
return result;
}
void DcmSegment::clearData()
{
+ m_SegmentNumber.clear();
m_SegmentDescription.clearData();
m_SegmentAlgorithmName.clear();
m_SegmentationAlgorithmIdentification.clearData();
}
// protected default constructor
+
DcmSegment::DcmSegment()
: m_SegmentationDoc(NULL)
+ , m_SegmentNumber(DCM_SegmentNumber)
, m_SegmentDescription()
, m_SegmentAlgorithmName(DCM_SegmentAlgorithmName)
, m_SegmentationAlgorithmIdentification()
, m_RecommendedDisplayCIELabValue(DCM_RecommendedDisplayCIELabValue)
, m_TrackingID(DCM_TrackingID)
, m_TrackingUID(DCM_TrackingUID)
- , m_Rules()
+ , m_Rules(new IODRules())
{
initIODRules();
}
void DcmSegment::initIODRules()
{
- m_Rules.addRule(new IODRule(DCM_SegmentAlgorithmName, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE),
+ m_Rules->addRule(new IODRule(DCM_SegmentNumber, "1", "1", "SegmentationImageModule", DcmIODTypes::IE_IMAGE),
OFTrue);
- m_Rules.addRule(
+ m_Rules->addRule(new IODRule(DCM_SegmentAlgorithmName, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE),
+ OFTrue);
+ m_Rules->addRule(
new IODRule(DCM_RecommendedDisplayGrayscaleValue, "1", "3", "SegmentationImageModule", DcmIODTypes::IE_IMAGE),
OFTrue);
- m_Rules.addRule(
+ m_Rules->addRule(
new IODRule(DCM_RecommendedDisplayCIELabValue, "3", "3", "SegmentationImageModule", DcmIODTypes::IE_IMAGE),
OFTrue);
- m_Rules.addRule(new IODRule(DCM_TrackingID, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
- m_Rules.addRule(new IODRule(DCM_TrackingUID, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
+ m_Rules->addRule(new IODRule(DCM_TrackingID, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
+ m_Rules->addRule(new IODRule(DCM_TrackingUID, "1", "1C", "SegmentationImageModule", DcmIODTypes::IE_IMAGE), OFTrue);
}
// -------------- getters --------------------
return DcmIODUtil::getStringValueFromElement(m_TrackingUID, value, pos);
}
+Uint16 DcmSegment::getSegmentNumberRead()
+{
+ OFVector<Uint16> values;
+ DcmIODUtil::getUint16ValuesFromElement(m_SegmentNumber, values);
+ if (values.size() >0 )
+ {
+ return values[0];
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+OFshared_ptr<IODRules> DcmSegment::getIODRules()
+{
+ return m_Rules;
+}
+
// -------------- setters --------------------
OFCondition DcmSegment::setSegmentLabel(const OFString& value, const OFBool checkValue)
/*
*
- * Copyright (C) 2015-2022, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
makeOFConditionConst(SG_EC_InvalidValue, OFM_dcmseg, 4, OF_error, "Invalid value for Segmentation SOP Class");
makeOFConditionConst(SG_EC_NotEnoughData, OFM_dcmseg, 5, OF_error, "Not enough data");
makeOFConditionConst(SG_EC_MaxFramesReached, OFM_dcmseg, 6, OF_error, "Maximum Number of Frames reached");
+makeOFConditionConst(SG_EC_InvalidBitDepth, OFM_dcmseg, 7, OF_error, "Invalid bit depth for given Segmentation Type");
+makeOFConditionConst(SG_EC_FramesNotParallel, OFM_dcmseg, 8, OF_error, "Frames are not parallel");
+makeOFConditionConst(SG_EC_NoSegmentationBasedSOPClass, OFM_dcmseg, 9, OF_error, "No segmentation SOP class (Segmentation or Label Map Segmentation SOP Class)");
+makeOFConditionConst(SG_EC_NoConversionRequired, OFM_dcmseg, 10, OF_ok, "Segmentation-based object does not require requested conversion");
+makeOFConditionConst(SG_EC_AlreadyLabelMap, OFM_dcmseg, 11, OF_error, "Segmentation-based object is already a label map");
+makeOFConditionConst(SG_EC_CannotConvertFractionalToLabelmap, OFM_dcmseg, 12, OF_error, "Cannot convert fractional to label map segmentations");
+makeOFConditionConst(SG_EC_OverlappingSegments, OFM_dcmseg, 13, OF_error, "Binary segmentation contains overlapping segments");
+makeOFConditionConst(SG_EC_CannotConvertMissingCIELab, OFM_dcmseg, 14, OF_error, "Cannot convert to PALETTE color model since not all segments contain Recommended Display CIELab Value Macro");
+makeOFConditionConst(SG_EC_MissingPlanePositionPatient, OFM_dcmseg, 15, OF_error, "Missing Plane Position (Patient) Functional Group");
DcmSegTypes::E_SegmentationType DcmSegTypes::OFString2Segtype(const OFString& value)
{
return DcmSegTypes::ST_BINARY;
if (value == "FRACTIONAL")
return DcmSegTypes::ST_FRACTIONAL;
+ if (value == "LABELMAP")
+ return DcmSegTypes::ST_LABELMAP;
else
return DcmSegTypes::ST_UNKNOWN;
}
return "BINARY";
case DcmSegTypes::ST_FRACTIONAL:
return "FRACTIONAL";
+ case DcmSegTypes::ST_LABELMAP:
+ return "LABELMAP";
case DcmSegTypes::ST_UNKNOWN:
return "UNKNOWN";
default:
return DcmSegTypes::SAT_UNKNOWN;
}
+
+OFString DcmSegTypes::labelmapColorModel2OFString(const DcmSegTypes::E_SegmentationLabelmapColorModel value, const OFString& fallbackValue)
+{
+ OFString result;
+ switch (value)
+ {
+ case DcmSegTypes::SLCM_MONOCHROME2:
+ return "MONOCHROME2";
+ case DcmSegTypes::SLCM_PALETTE:
+ return "PALETTE COLOR";
+ case DcmSegTypes::SLCM_UNKNOWN:
+ result = "UNKNOWN";
+ default:
+ result = "Invalid labelmap color model (internal error)";
+ }
+ if (!fallbackValue.empty())
+ {
+ DCMSEG_WARN("Invalid value for label map color model: " << result << ". Using fallback value: " << fallbackValue);
+ result = fallbackValue;
+ }
+ return result;
+}
+
+
+DcmSegTypes::E_SegmentationLabelmapColorModel DcmSegTypes::OFString2LabelmapColorModel(const OFString& value)
+{
+ if (value == "MONOCHROME2")
+ return DcmSegTypes::SLCM_MONOCHROME2;
+ if (value == "PALETTE COLOR")
+ return DcmSegTypes::SLCM_PALETTE;
+ else
+ return DcmSegTypes::SLCM_UNKNOWN;
+}
+
SegmentDescriptionMacro::SegmentDescriptionMacro()
: m_SegmentLabel(DCM_SegmentLabel)
, m_SegmentDescription(DCM_SegmentDescription)
{
}
+SegmentDescriptionMacro& SegmentDescriptionMacro::operator=(const SegmentDescriptionMacro& rhs)
+{
+ if (this != &rhs)
+ {
+ m_SegmentLabel = rhs.m_SegmentLabel;
+ m_SegmentDescription = rhs.m_SegmentDescription;
+ m_SegmentAlgorithmType = rhs.m_SegmentAlgorithmType;
+ m_GeneralAnatomyCode = rhs.m_GeneralAnatomyCode;
+ m_SegmentedPropertyCategoryCode = rhs.m_SegmentedPropertyCategoryCode;
+ m_SegmentedPropertyType = rhs.m_SegmentedPropertyType;
+ }
+ return *this;
+}
+
+
+SegmentDescriptionMacro* SegmentDescriptionMacro::clone()
+{
+ return new SegmentDescriptionMacro(*this);
+}
+
+
void SegmentDescriptionMacro::clearData()
{
m_SegmentLabel.clear();
{
}
+SegmentedPropertyTypeCodeItem& SegmentedPropertyTypeCodeItem::operator=(const SegmentedPropertyTypeCodeItem& rhs)
+{
+ if (this != &rhs)
+ {
+ m_SegmentedPropertyTypeCode = rhs.m_SegmentedPropertyTypeCode;
+ DcmIODUtil::copyContainer(rhs.m_SegmentedPropertyTypeModifierCode, m_SegmentedPropertyTypeModifierCode);
+ }
+ return *this;
+}
+
+SegmentedPropertyTypeCodeItem* SegmentedPropertyTypeCodeItem::clone()
+{
+ return new SegmentedPropertyTypeCodeItem(*this);
+}
+
+SegmentedPropertyTypeCodeItem::SegmentedPropertyTypeCodeItem(const SegmentedPropertyTypeCodeItem& rhs)
+ : m_SegmentedPropertyTypeCode(rhs.m_SegmentedPropertyTypeCode)
+ , m_SegmentedPropertyTypeModifierCode()
+{
+ DcmIODUtil::copyContainer(rhs.m_SegmentedPropertyTypeModifierCode, m_SegmentedPropertyTypeModifierCode);
+}
+
SegmentedPropertyTypeCodeItem::~SegmentedPropertyTypeCodeItem()
{
DcmIODUtil::freeContainer(m_SegmentedPropertyTypeModifierCode);
/*
*
- * Copyright (C) 2015-2024, Open Connections GmbH
+ * Copyright (C) 2015-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
#include "dcmtk/dcmiod/iodtypes.h"
#include "dcmtk/dcmseg/segtypes.h"
+#include <iostream>
#include "dcmtk/dcmseg/segutils.h"
-DcmIODTypes::Frame* DcmSegUtils::packBinaryFrame(const Uint8* pixelData, const Uint16 rows, const Uint16 columns)
-{
- // Sanity checking
- const size_t totalBits = OFstatic_cast(size_t, rows) * columns;
- if (totalBits == 0)
- {
- DCMSEG_ERROR("Unable to pack binary segmentation frame: Rows or Columns is 0");
- return NULL;
- }
- if (!pixelData)
- {
- DCMSEG_ERROR("Unable to pack binary segmentation frame: No pixel data provided");
- return NULL;
- }
-
- // Calculate total number of bytes required
- size_t totalBytes = (totalBits + 7) / 8; // +7 to round up to the nearest byte
-
- // Allocate memory for the packed bit array
- Uint8* packedData = new Uint8[totalBytes];
- if (packedData == NULL)
- {
- DCMSEG_ERROR("Cannot allocate memory for packed binary frame");
- return NULL;
- }
- memset(packedData, 0, totalBytes); // Initialize to 0
-
- // Pack the bits
- for (Uint32 i = 0; i < totalBits; ++i) {
- if (pixelData[i] != 0) {
- Uint32 byteIndex = i / 8;
- Uint32 bitIndex = i % 8;
- DCMSEG_TRACE("bitIndex: " << bitIndex << ", byteIndex: " << byteIndex << ", packedData[byteIndex]: " << DcmSegUtils::debugByte2Bin(packedData[byteIndex]));
- packedData[byteIndex] |= (1 << bitIndex); // Fill from right to left
- }
- }
-
- // Create and return the frame
- DcmIODTypes::Frame* frame = new DcmIODTypes::Frame();
- if (frame == NULL)
- {
- DCMSEG_ERROR("Cannot allocate memory for packed binary frame");
- delete[] packedData;
- return NULL;
- }
- frame->pixData = packedData;
- frame->length = totalBytes;
- return frame;
-}
-
-OFCondition DcmSegUtils::concatBinaryFrames(const OFVector<DcmIODTypes::Frame*>& frames,
+OFCondition DcmSegUtils::concatBinaryFrames(const OFVector<DcmIODTypes::FrameBase*>& frames,
const Uint16 rows,
const Uint16 cols,
Uint8* pixData,
}
// Initialize the target pixData array to 0
- std::memset(pixData, 0, pixDataLength);
+ memset(pixData, 0, pixDataLength);
// Concatenate the bits
- Uint32 bitIndex = 0;
+ size_t bitIndex = 0;
+
for (size_t frameIndex = 0; frameIndex < frames.size(); ++frameIndex)
{
- const DcmIODTypes::Frame* frame = frames[frameIndex];
- Uint32 frameBits = rows * cols;
- for (Uint32 i = 0; i < frameBits; ++i)
+ // Make sure frame has correct bit depth
+ if (frames[frameIndex]->bytesPerPixel() != 1)
{
- Uint32 byteIndex = i / 8;
- Uint32 bitPos = i % 8;
- if (frame->pixData[byteIndex] & (1 << bitPos % 8)) {
- Uint32 targetByteIndex = bitIndex / 8;
- Uint32 targetBitPos = bitIndex % 8;
- pixData[targetByteIndex] |= (1 << targetBitPos);
- DCMSEG_TRACE("Setting bit at targetByteIndex: " << targetByteIndex << ", targetBitPos: " << targetBitPos << ", frame->pixData[" << byteIndex << "]: " << DcmSegUtils::debugByte2Bin(frame->pixData[byteIndex]) << ", value: " << DcmSegUtils::debugByte2Bin(pixData[targetByteIndex]));
+ DCMSEG_ERROR("Cannot concatenate frames with bits allocated != 1");
+ return EC_IllegalParameter;
+ }
+ // Cast the frame to the appropriate type to make access easier
+ DcmIODTypes::Frame<Uint8>* frame = OFstatic_cast(DcmIODTypes::Frame<Uint8>*,frames[frameIndex]);
+ size_t frameBits = rows * cols;
+ // If a frame always has bytes fully packed, i.e. number of bits i a multiple of 8,
+ // we can copy the bytes directly and don't have to fiddle with the bits
+ if (frameBits % 8 == 0)
+ {
+ size_t bytesToCopy = frameBits / 8;
+ memcpy(pixData + (bitIndex / 8), frame->getPixelData(), bytesToCopy);
+ DCMSEG_TRACE("Copying " << bytesToCopy << " bytes from frame " << frameIndex << " to pixData at index " << (bitIndex / 8));
+ bitIndex += frameBits;
+ }
+ else
+ {
+ // we need to copy bitwise, so we iterate over the bits
+ DCMSEG_TRACE("Copying " << frameBits << " bits from frame " << frameIndex << " to pixData at index " << (bitIndex / 8));
+ for (size_t i = 0; i < frameBits; ++i)
+ {
+ size_t byteIndex = i / 8;
+ size_t bitPos = i % 8;
+ if (frame->m_pixData[byteIndex] & (1 << bitPos % 8)) {
+ size_t targetByteIndex = bitIndex / 8;
+ size_t targetBitPos = bitIndex % 8;
+ pixData[targetByteIndex] |= (1 << targetBitPos);
+ DCMSEG_TRACE("Setting bit at targetByteIndex: " << targetByteIndex << ", targetBitPos: " << targetBitPos << ", frame->pixData[" << byteIndex << "]: " << DcmSegUtils::debugByte2Bin(OFstatic_cast(Uint8*, frame->getPixelData())[byteIndex]) << ", value: " << DcmSegUtils::debugByte2Bin(pixData[targetByteIndex]));
+ }
+ bitIndex++;
}
- bitIndex++;
}
}
}
-DcmIODTypes::Frame* DcmSegUtils::unpackBinaryFrame(const DcmIODTypes::Frame* frame, Uint16 rows, Uint16 cols)
+DcmIODTypes::Frame<Uint8>* DcmSegUtils::unpackBinaryFrame(const DcmIODTypes::Frame<Uint8>* frame, Uint16 rows, Uint16 cols)
{
// Sanity checking
if ((frame == NULL) || (rows == 0) || (cols == 0))
Uint32 totalPixels = rows * cols;
// Allocate memory for the unpacked pixel data
- DcmIODTypes::Frame* result = new DcmIODTypes::Frame();
+ DcmIODTypes::Frame<Uint8>* result = new DcmIODTypes::Frame<Uint8>();
if (result == NULL)
{
DCMSEG_ERROR("Cannot allocate memory for unpacked binary frame");
return NULL;
}
- result->pixData = new Uint8[totalPixels];
- if (result->pixData == NULL)
+ result->m_pixData = new Uint8[totalPixels];
+ if (result->m_pixData == NULL)
{
DCMSEG_ERROR("Cannot allocate memory for unpacked binary frame");
delete result;
return NULL;
}
- result->length = totalPixels;
- memset(result->pixData, 0, totalPixels); // Initialize to 0
+ result->m_numPixels = totalPixels;
+ memset(result->m_pixData, 0, totalPixels); // Initialize to 0
// Unpack the bits
for (Uint32 i = 0; i < totalPixels; ++i) {
Uint32 byteIndex = i / 8;
Uint32 bitIndex = i % 8;
- if (frame->pixData[byteIndex] & (1 << (bitIndex))) {
- result->pixData[i] = 1;
+ if (frame->m_pixData[byteIndex] & (1 << (bitIndex))) {
+ result->m_pixData[i] = 1;
} else
{
- result->pixData[i] = 0;
+ result->m_pixData[i] = 0;
}
}
-
return result;
}
}
return result;
}
-
# declare executables
DCMTK_ADD_TEST_EXECUTABLE(dcmseg_tests
tbigdim.cc
+ tconcat_binary.cc
tests.cc
- tutils.cc
+ tlabelmap.cc
troundtrip.cc
- tconcat_binary.cc
+ tutils.cc
)
# make sure executables are linked to the corresponding libraries
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
../../dcmdata/include/dcmtk/dcmdata/dclist.h \
../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \
- ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \
../../ofstd/include/dcmtk/ofstd/ofmap.h ../include/dcmtk/dcmseg/segdoc.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
../../dcmfg/include/dcmtk/dcmfg/fg.h \
../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmiod/include/dcmtk/dcmiod/iodimage.h \
../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modiccprofile.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \
- ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segment.h \
+ ../include/dcmtk/dcmseg/segtypes.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
+ ../include/dcmtk/dcmseg/segutils.h \
../../ofstd/include/dcmtk/ofstd/oftest.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h
-troundtrip.o: troundtrip.cc ../../config/include/dcmtk/config/osconfig.h \
+tlabelmap.o: tlabelmap.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \
+ ../include/dcmtk/dcmseg/segdoc.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fg.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modfor.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvriant.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/stralias.def \
+ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modiccprofile.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \
+ ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segment.h \
+ ../include/dcmtk/dcmseg/segtypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
+ ../include/dcmtk/dcmseg/segutils.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdate.h \
+ ../../ofstd/include/dcmtk/ofstd/oftime.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgpixmsr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \
+ ../../ofstd/include/dcmtk/ofstd/oftempf.h
+tpacking.o: tpacking.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmseg/segdoc.h \
../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \
../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \
- ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../dcmfg/include/dcmtk/dcmfg/fginterface.h \
../../dcmfg/include/dcmtk/dcmfg/fg.h \
../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmiod/include/dcmtk/dcmiod/iodimage.h \
../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modiccprofile.h \
../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \
- ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segment.h \
+ ../include/dcmtk/dcmseg/segtypes.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
- ../include/dcmtk/dcmseg/segment.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
+ ../include/dcmtk/dcmseg/segutils.h \
../../ofstd/include/dcmtk/ofstd/oftest.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \
../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \
- ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
../../dcmdata/include/dcmtk/dcmdata/dcdict.h \
../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \
../../ofstd/include/dcmtk/ofstd/oftempf.h
-tutils.o: tutils.cc ../../config/include/dcmtk/config/osconfig.h \
- ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
- ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+troundtrip.o: troundtrip.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmseg/segdoc.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
../../oflog/include/dcmtk/oflog/oflog.h \
../../oflog/include/dcmtk/oflog/logger.h \
../../oflog/include/dcmtk/oflog/config.h \
- ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
- ../../ofstd/include/dcmtk/ofstd/ofcast.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
../../oflog/include/dcmtk/oflog/config/defines.h \
../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
../../oflog/include/dcmtk/oflog/loglevel.h \
../../ofstd/include/dcmtk/ofstd/ofvector.h \
- ../../ofstd/include/dcmtk/ofstd/oftypes.h \
../../oflog/include/dcmtk/oflog/tstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstring.h \
- ../../ofstd/include/dcmtk/ofstd/ofstream.h \
../../oflog/include/dcmtk/oflog/tchar.h \
../../oflog/include/dcmtk/oflog/spi/apndatch.h \
../../oflog/include/dcmtk/oflog/appender.h \
../../ofstd/include/dcmtk/ofstd/ofmem.h \
../../ofstd/include/dcmtk/ofstd/ofutil.h \
- ../../ofstd/include/dcmtk/ofstd/oftraits.h \
../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
../../oflog/include/dcmtk/oflog/layout.h \
../../oflog/include/dcmtk/oflog/streams.h \
../../oflog/include/dcmtk/oflog/logmacro.h \
../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
../../oflog/include/dcmtk/oflog/tracelog.h \
- ../../ofstd/include/dcmtk/ofstd/ofcond.h \
- ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
- ../../ofstd/include/dcmtk/ofstd/diag/push.def \
- ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
- ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationcreator.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../dcmfg/include/dcmtk/dcmfg/concatenationloader.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fg.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgseg.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modfor.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvriant.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/stralias.def \
+ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modiccprofile.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modsegmentationseries.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h \
+ ../include/dcmtk/dcmseg/segdef.h ../include/dcmtk/dcmseg/segment.h \
+ ../include/dcmtk/dcmseg/segtypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrst.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrut.h \
+ ../include/dcmtk/dcmseg/segutils.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdate.h \
+ ../../ofstd/include/dcmtk/ofstd/oftime.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgpixmsr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \
+ ../../ofstd/include/dcmtk/ofstd/oftempf.h
+tutils.o: tutils.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmseg/segutils.h ../include/dcmtk/dcmseg/segdef.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
../include/dcmtk/dcmseg/segtypes.h \
../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
../../ofstd/include/dcmtk/ofstd/ofglobal.h \
../../ofstd/include/dcmtk/ofstd/ofthread.h \
../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/oflist.h \
../../dcmiod/include/dcmtk/dcmiod/modbase.h \
../../ofstd/include/dcmtk/ofstd/ofexbl.h \
../../ofstd/include/dcmtk/ofstd/ofconsol.h \
../../ofstd/include/dcmtk/ofstd/ofexit.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcuid.h
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../ofstd/include/dcmtk/ofstd/oftime.h
dcmdatadir = $(top_srcdir)/../dcmdata
dcmioddir = $(top_srcdir)/../dcmiod
dcmfgdir = $(top_srcdir)/../dcmfg
+dcmimgledir = $(top_srcdir)/../dcmimgle
LIBDIRS = -L$(top_srcdir)/libsrc -L$(ofstddir)/libsrc -L$(oflogdir)/libsrc \
-L$(dcmdatadir)/libsrc -L$(dcmioddir)/libsrc -L$(dcmfgdir)/libsrc \
- -L$(oficonvdir)/libsrc
-LOCALLIBS = -ldcmseg -ldcmfg -ldcmiod -ldcmdata -loflog -lofstd -loficonv $(ZLIBLIBS) \
- $(CHARCONVLIBS) $(MATHLIBS)
+ -L$(oficonvdir)/libsrc -L$(dcmimgledir)/libsrc
+
+LOCALLIBS = -ldcmseg -ldcmfg -ldcmiod -ldcmimgle -ldcmdata \
+ -loflog -lofstd -loficonv $(ZLIBLIBS) $(CHARCONVLIBS) $(MATHLIBS)
+
LOCALINCLUDES = -I$(top_srcdir)/include -I$(ofstddir)/include -I$(oflogdir)/include \
- -I$(dcmdatadir)/include -I$(dcmioddir)/include -I$(dcmfgdir)/include \
+ -I$(dcmdatadir)/include -I$(dcmioddir)/include -I$(dcmfgdir)/include
-test_objs = tbigdim.o tconcat_binary.o tests.o troundtrip.o tutils.o
+test_objs = tbigdim.o tconcat_binary.o tests.o tlabelmap.o troundtrip.o tutils.o
objs = $(test_objs)
progs = tests
/*
*
- * Copyright (C) 2022-2024, OFFIS e.V.
+ * Copyright (C) 2022-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/oftest.h"
#include "dcmtk/dcmseg/segtypes.h" /* for DCMSEG_DEBUG */
+// DCMTK's original OFMap implementation is too slow for this test...
#ifdef HAVE_STL_MAP
#include "dcmtk/dcmseg/segdoc.h"
#include "dcmtk/dcmseg/segment.h"
#include "dcmtk/dcmfg/fgpixmsr.h"
#include "dcmtk/dcmfg/fgplanor.h"
#include "dcmtk/dcmfg/fgplanpo.h"
-#include "dcmtk/dcmfg/fgseg.h"
#include "dcmtk/dcmiod/iodmacro.h"
#include "dcmtk/dcmdata/dcxfer.h"
#include "dcmtk/dcmdata/dcdict.h"
static const Uint8 NUM_ROWS = 5;
static const Uint8 NUM_COLS = 5;
+static const Uint8 NUM_THREADS = 16; // Use 16 threads for writing and reading
// Restrict to 1.000.000 Frames since the theoretical 2^31-1 number of frames
// results in too much memory usage and waiting time
+
static const Uint32 NUM_FRAMES = 1000000;
-static const Uint16 NUM_SEGS = DCM_SEG_MAX_SEGMENTS;
+static const size_t NUM_SEGS = DCM_SEG_MAX_SEGMENTS;
static const Uint8 NUM_PIXELS_PER_FRAME = NUM_COLS * NUM_ROWS;
DcmDataset* ds = dcmff.getDataset();
seg->setCheckDimensionsOnWrite(OFFalse);
seg->setCheckFGOnWrite(OFFalse);
+ seg->getFunctionalGroups().setUseThreads(NUM_THREADS);
OFCondition result = seg->writeDataset(*ds);
OFCHECK(result.good());
OFString temp_fn = tf.getFilename();
OFCHECK(!temp_fn.empty());
OFCHECK(dcmff.saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good());
+ tf.stealFile();
// Read object from dataset into DcmSegmentation object, write again to dataset and
// check whether object after writing is identical to object after writing.
// the same expected result
delete seg;
seg = NULL;
- DcmSegmentation::loadFile(temp_fn, seg).good();
+ DcmSegmentation::LoadingFlags flags;
+ flags.m_numThreads = NUM_THREADS; // Use 16 threads for reading
+ DcmSegmentation::loadFile(temp_fn, seg, flags).good();
OFCHECK(seg != OFnullptr);
if (seg)
{
DcmDataset dset;
seg->setCheckDimensionsOnWrite(OFFalse);
seg->setCheckFGOnWrite(OFFalse);
+ seg->getFunctionalGroups().setUseThreads(NUM_THREADS);
OFCHECK(seg->writeDataset(dset).good());
checkCreatedObject(dset);
delete seg;
if (!seg)
return;
- FGSegmentation* fg_seg = new FGSegmentation();
FGFrameContent* fg = new FGFrameContent();
- OFCHECK(fg && fg_seg);
+ OFCHECK(fg);
fg->setStackID("1");
if (fg)
{
{
data[i] = i;
}
- OFCHECK(fg_seg->setReferencedSegmentNumber(frameNo % (DCM_SEG_MAX_SEGMENTS + 1)).good()); // limit/loop to 16 bit
+ Uint16 segmentNumber = OFstatic_cast(Uint16, ((frameNo-1) % (NUM_SEGS)) +1); // segment numbers start at 1
OFVector<FGBase*> perFrameFGs;
perFrameFGs.push_back(fg);
- perFrameFGs.push_back(fg_seg);
- OFCHECK(seg->addFrame(data, frameNo % (DCM_SEG_MAX_SEGMENTS + 1), perFrameFGs).good());
+ OFCHECK(seg->addFrame(data, segmentNumber, perFrameFGs).good());
delete[] data;
}
}
delete fg;
- delete fg_seg;
}
static void addDimensions(DcmSegmentation* seg)
OFCHECK(dset.findAndGetSequence(DCM_PerFrameFunctionalGroupsSequence, seq).good());
if (seq != NULL)
{
- size_t card = seq->card();
- OFCHECK(card == NUM_FRAMES);
+ size_t numFrames = seq->card();
+ OFOStringStream oss;
+ oss << "Expected " << NUM_FRAMES << " frames, but got " << numFrames;
+ OFCHECK_MSG(numFrames == NUM_FRAMES, oss.str().c_str());
DcmItem* item = seq->getItem(0);
- for (size_t n = 0; (n < card) && (item != NULL); n++)
+ for (size_t n = 0; (n < numFrames) && (item != NULL); n++)
{
DcmItem* fgItem = NULL;
OFCHECK(item->findAndGetSequenceItem(DCM_SegmentIdentificationSequence, fgItem, 0).good());
{
Uint16 segNum = 0;
OFCHECK(fgItem->findAndGetUint16(DCM_ReferencedSegmentNumber, segNum).good());
- OFCHECK(segNum == ((n + 1) % (DCM_SEG_MAX_SEGMENTS + 1)));
+ OFCHECK(segNum == ((n % NUM_SEGS) + 1));
}
item = OFstatic_cast(DcmItem*, seq->nextInContainer(item));
/*
*
- * Copyright (C) 2019-2024, OFFIS e.V.
+ * Copyright (C) 2019-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
ConcatenationCreator cc;
result = cc.setCfgFramesPerInstance(NUM_FRAMES_PER_CONCAT);
+ OFCHECK_MSG(result.good(), "Could not configure Concatenation Frames per Instance");
if (result.good())
{
seg->setCheckFGOnWrite(OFFalse);
result = seg->writeConcatenation(cc);
+ OFCHECK_MSG(result.good(), "Could not write Concatenation");
if (result.good())
{
size_t n = 0;
{
if (cl.getInfo().size() == 1)
{
- OFVector<DcmIODTypes::Frame*> frames;
+ OFVector<DcmIODTypes::Frame<Uint8>*> frames;
DcmFileFormat dcmff;
result = DcmSegmentation::loadConcatenation(cl, cl.getInfo().begin()->first, seg);
if (result.good())
/*
*
- * Copyright (C) 2015-2024, OFFIS e.V.
+ * Copyright (C) 2015-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFTEST_REGISTER(dcmseg_concatBinaryFrames);
OFTEST_REGISTER(dcmseg_roundtrip);
OFTEST_REGISTER(dcmseg_concat_binary);
-
+OFTEST_REGISTER(dcmseg_labelmap_8bit_mono2);
+OFTEST_REGISTER(dcmseg_labelmap_16bit_mono2);
+OFTEST_REGISTER(dcmseg_labelmap_8bit_palette);
+OFTEST_REGISTER(dcmseg_labelmap_16bit_palette);
OFTEST_MAIN("dcmseg")
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, Open Connections GmbH
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmseg
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Test for creating, writing and reading labelmap segmentations
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/dcmdata/dcdatset.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/dcmdata/dcsequen.h"
+#include "dcmtk/dcmiod/modpalettecolorlut.h"
+#include "dcmtk/dcmseg/segdoc.h"
+#include "dcmtk/dcmseg/segment.h"
+#include "dcmtk/dcmseg/segtypes.h"
+#include "dcmtk/ofstd/oftest.h"
+#include "dcmtk/dcmfg/fgfracon.h"
+#include "dcmtk/dcmfg/fgpixmsr.h"
+#include "dcmtk/dcmfg/fgplanor.h"
+#include "dcmtk/dcmfg/fgplanpo.h"
+#include "dcmtk/dcmiod/iodmacro.h"
+#include "dcmtk/dcmdata/dcxfer.h"
+#include "dcmtk/dcmdata/dcdict.h"
+#include "dcmtk/ofstd/ofmem.h"
+#include "dcmtk/ofstd/oftempf.h"
+#include "dcmtk/ofstd/oftest.h"
+#include "dcmtk/ofstd/oftypes.h"
+
+// Dimensions are 510 x 257 = 65535 pixels per frame.
+// This allows to count through 16 bit values from 0 to 65534 for each frame. We are not using value
+// up to 65535 since that would result in 65536 values; since each value represents a segment requiring
+// an entry in the Segment Sequence, we would exceed the maximum number of segments (65535) allowed in
+// a segmentation object (Segment Number is of VR US).
+// For 8 bit, the pixel are counted through repeatedly from 0 to 255. This does not match exactly on the
+// number of pixels (510*257) per frame but should be sufficient for testing purposes. 255 is chosen
+// because this will also exercise the maximum number of palette entries (256) in the palette color LUT.
+static const Uint16 NUM_ROWS = 510;
+static const Uint16 NUM_COLS = 257;
+// Two frames to exercise multi-frame
+static const Uint16 NUM_FRAMES = 2;
+static const size_t NUM_PIXELS_PER_FRAME = NUM_COLS * NUM_ROWS;
+
+
+// set to true to keep temporary files for debugging
+static const OFBool keepTempFiles = OFFalse;
+
+// For 8 bit, pixel values 0 to 255 are permitted.
+// For 16 bit, pixel values 0 to 65534 are permitted, since for labelmaps the pixel
+// value represents the segment number as well, and DICOM permits a maximum segment number
+// of 65535.
+
+// Since the number of segments in the 16 bit case is very large and generation takes
+// some time, the 16 bits are marked as slow.
+
+static DcmSegmentation* createLabelMap(const Uint8 bits_allocated, const DcmSegTypes::E_SegmentationLabelmapColorModel cm);
+static void setGenericValues(DcmSegmentation* seg);
+static void addSharedFGs(DcmSegmentation* seg);
+static void addPaletteAndICCProfile(DcmSegmentation* seg, const Uint8 bitsAllocated);
+template<typename T>
+static void addFrames(DcmSegmentation* seg, const Uint8 bitsAllocated);
+static void addSegments(DcmSegmentation *seg, const Uint8 bitsAllocated);
+static void addDimensions(DcmSegmentation* seg);
+static void checkCreatedObject(DcmDataset* dset, const Uint8 bits_allocated, const DcmSegTypes::E_SegmentationLabelmapColorModel cm);
+static void checkPalette(DcmDataset* dset, const Uint8 bits_allocated);
+
+
+// Concatenations tests: TBD
+// static void writeAndCheckConcatenation(DcmSegmentation* seg, OFList<OFFilename>& concats);
+// static void loadAndCheckConcatenation(const OFList<OFFilename>& concats);
+// static void checkConcatenationInstance(size_t numInstance, DcmSegmentation* srcInstance, DcmDataset* concatInstance);
+
+OFTEST(dcmseg_labelmap_8bit_mono2)
+{
+ // Make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
+ return;
+ }
+
+ // Creation
+ DcmSegmentation* seg = createLabelMap(8, DcmSegTypes::SLCM_MONOCHROME2);
+ setGenericValues(seg);
+ addSharedFGs(seg);
+ addFrames<Uint8>(seg, 8);
+ addSegments(seg, 8);
+ addDimensions(seg);
+
+ // Write to dataset and compare its dump with expected result
+ DcmFileFormat dcmff;
+ DcmDataset* created_ds = dcmff.getDataset();
+ OFCHECK(seg->writeDataset(*created_ds).good());
+ checkCreatedObject(created_ds, 8, DcmSegTypes::SLCM_MONOCHROME2);
+
+ // Save to disk, and re-load to test import
+ OFTempFile tf;
+ OFString temp_fn = tf.getFilename();
+ OFCHECK(!temp_fn.empty());
+ OFCHECK(seg->saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good());
+
+ // Read object from dataset into DcmSegmentation object, write again to dataset and
+ // check whether object after writing is identical to object after writing.
+ // the same expected result
+ delete seg;
+ seg = NULL;
+ DcmDataset loaded_ds;
+ DcmSegmentation::loadFile(temp_fn, seg).good();
+ OFCHECK(seg != OFnullptr);
+ if (seg)
+ {
+ OFCHECK(seg->writeDataset(loaded_ds).good());
+ checkCreatedObject(&loaded_ds, 8, DcmSegTypes::SLCM_MONOCHROME2);
+ }
+ if (keepTempFiles)
+ {
+ std::cout << "Keeping temporary file: " << temp_fn << " from test dcmseg_labelmap_8bit_mono2" << std::endl;
+ tf.stealFile();
+ }
+ delete seg;
+}
+
+
+OFTEST_FLAGS(dcmseg_labelmap_16bit_mono2, EF_Slow)
+{
+ // Make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
+ return;
+ }
+
+ // Creation
+ DcmSegmentation* seg_object = createLabelMap(16, DcmSegTypes::SLCM_MONOCHROME2);
+ setGenericValues(seg_object);
+ addSharedFGs(seg_object);
+ addFrames<Uint16>(seg_object, 16);
+ addSegments(seg_object, 16);
+ addDimensions(seg_object);
+
+ // Write to dataset and compare its dump with expected result
+ DcmFileFormat dcmff;
+ DcmDataset* dset_created = dcmff.getDataset();
+ OFCHECK(seg_object->writeDataset(*dset_created).good());
+ checkCreatedObject(dset_created, 16, DcmSegTypes::SLCM_MONOCHROME2);
+
+ // Save to disk, and re-load to test import
+ OFTempFile tf;
+ OFString temp_fn = tf.getFilename();
+ OFCHECK(!temp_fn.empty());
+ OFCHECK(seg_object->saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good());
+
+ // Read object from dataset into DcmSegmentation object, write again to dataset and
+ // check whether object after writing is identical to object after writing.
+ // the same expected result
+ delete seg_object;
+ seg_object = NULL;
+ DcmSegmentation::loadFile(temp_fn, seg_object).good();
+ OFCHECK(seg_object != OFnullptr);
+ DcmDataset dset_loaded;
+ if (seg_object)
+ {
+ OFCHECK(seg_object->writeDataset(dset_loaded).good());
+ checkCreatedObject(&dset_loaded, 16, DcmSegTypes::SLCM_MONOCHROME2);
+ }
+
+ delete seg_object;
+ if (keepTempFiles)
+ {
+ std::cout << "Keeping temporary file: " << temp_fn << " from test dcmseg_labelmap_16bit_mono2" << std::endl;
+ tf.stealFile();
+ }
+}
+
+OFTEST(dcmseg_labelmap_8bit_palette)
+{
+ // Make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
+ return;
+ }
+
+ // Creation
+ DcmSegmentation* seg = createLabelMap(8, DcmSegTypes::SLCM_PALETTE);
+ setGenericValues(seg);
+ addSharedFGs(seg);
+ addFrames<Uint8>(seg, 8);
+ addSegments(seg, 8);
+ addDimensions(seg);
+ addPaletteAndICCProfile(seg, 8);
+
+ // Write to dataset and compare its dump with expected result
+ DcmFileFormat dcmff;
+ DcmDataset* created_ds = dcmff.getDataset();
+ OFCHECK(seg->writeDataset(*created_ds).good());
+ checkCreatedObject(created_ds, 8, DcmSegTypes::SLCM_PALETTE);
+
+ // Save to disk, and re-load to test import
+ OFTempFile tf;
+ OFString temp_fn = tf.getFilename();
+ OFCHECK(!temp_fn.empty());
+ OFCHECK(seg->saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good());
+
+ // Read object from dataset into DcmSegmentation object, write again to dataset and
+ // check whether object after writing is identical to object after writing.
+ // the same expected result
+ delete seg;
+ seg = NULL;
+ DcmDataset loaded_ds;
+ DcmSegmentation::loadFile(temp_fn, seg).good();
+ OFCHECK(seg != OFnullptr);
+ if (seg)
+ {
+ seg->writeDataset(loaded_ds).good();
+ checkCreatedObject(&loaded_ds, 8, DcmSegTypes::SLCM_PALETTE);
+ }
+
+ delete seg;
+ if (keepTempFiles)
+ {
+ std::cout << "Keeping temporary file: " << temp_fn << " from test dcmseg_labelmap_8bit_palette" << std::endl;
+ tf.stealFile();
+ }
+}
+
+
+OFTEST_FLAGS(dcmseg_labelmap_16bit_palette, EF_Slow)
+{
+ // Make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
+ return;
+ }
+
+ // Creation
+ DcmSegmentation* seg_object = createLabelMap(16, DcmSegTypes::SLCM_PALETTE);
+ setGenericValues(seg_object);
+ addSharedFGs(seg_object);
+ addFrames<Uint16>(seg_object, 16);
+ addSegments(seg_object, 16);
+ addDimensions(seg_object);
+ addPaletteAndICCProfile(seg_object, 16);
+
+ // Write to dataset and compare its dump with expected result
+ DcmFileFormat dcmff;
+ DcmDataset* dset_created = dcmff.getDataset();
+ OFCHECK(seg_object->writeDataset(*dset_created).good());
+ checkCreatedObject(dset_created, 16, DcmSegTypes::SLCM_PALETTE);
+
+ // Save to disk, and re-load to test import
+ OFTempFile tf;
+ OFString temp_fn = tf.getFilename();
+ OFCHECK(!temp_fn.empty());
+ OFCHECK(seg_object->saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good());
+
+ // Read object from dataset into DcmSegmentation object, write again to dataset and
+ // check whether object after writing is identical to object after writing.
+ // the same expected result
+ delete seg_object;
+ seg_object = NULL;
+ DcmSegmentation::loadFile(temp_fn, seg_object).good();
+ OFCHECK(seg_object != OFnullptr);
+ DcmDataset dset_loaded;
+ if (seg_object)
+ {
+ seg_object->writeDataset(dset_loaded).good();
+ checkCreatedObject(&dset_loaded, 16, DcmSegTypes::SLCM_PALETTE);
+ }
+
+ delete seg_object;
+ if (keepTempFiles)
+ {
+ std::cout << "Keeping temporary file: " << temp_fn << " from test dcmseg_labelmap_16bit_palette" << std::endl;
+ tf.stealFile();
+ }
+}
+
+
+static DcmSegmentation* createLabelMap(const Uint8 bits_allocated, const DcmSegTypes::E_SegmentationLabelmapColorModel cm)
+{
+ IODGeneralEquipmentModule::EquipmentInfo eq("Open Connections", "OC CT", "4711", "0.1");
+ ContentIdentificationMacro ci("1", "LABEL", "DESCRIPTION", "Doe^John");
+ DcmSegmentation* seg = NULL;
+ OFCondition result;
+ DcmSegmentation::createLabelmapSegmentation(seg, NUM_ROWS, NUM_COLS, eq, ci, bits_allocated == 16, cm);
+ OFCHECK(result.good());
+ OFCHECK(seg != OFnullptr);
+ return seg;
+}
+
+static void setGenericValues(DcmSegmentation* seg)
+{
+ if (!seg)
+ return;
+ OFCHECK(seg->getPatient().setPatientName("Bond^James").good());
+ OFCHECK(seg->getPatient().setPatientID("007").good());
+ OFCHECK(seg->getPatient().setPatientBirthDate("19771007").good());
+ OFCHECK(seg->getStudy().setStudyDate("20190801").good());
+ OFCHECK(seg->getStudy().setStudyTime("120000").good());
+ OFCHECK(seg->getStudy().setStudyID("1").good());
+ OFCHECK(seg->getPatientStudy().setPatientAge("040Y").good());
+ OFCHECK(seg->getSeries().setSeriesDescription("Test Description").good());
+ OFCHECK(seg->getSeries().setSeriesNumber("1").good());
+ OFCHECK(seg->getSeries().setPatientPosition("HFS").good());
+
+ // Those values are usually computed automatically. UIDS are generated and date/times are set to current values.
+ // But in order to compare the "old" dump with the freshly created image attributes, we set some values manually,
+ // so that they are not overwritten with new, automatically created values later.
+ OFCHECK(seg->getStudy().setStudyInstanceUID("1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811").good());
+ OFCHECK(seg->getFrameOfReference().setFrameOfReferenceUID("2.25.30853397773651184949181049330553108086").good());
+ OFCHECK(seg->getSeries().setSeriesInstanceUID("1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812").good());
+ OFCHECK(seg->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good());
+ OFCHECK(seg->getGeneralImage().setContentDate("20190927").good());
+ OFCHECK(seg->getGeneralImage().setContentTime("153857").good());
+ OFCHECK(seg->getGeneralImage().setContentTime("153857").good());
+}
+
+
+static void addSharedFGs(DcmSegmentation* seg)
+{
+ if (!seg)
+ return;
+
+ FGPixelMeasures meas;
+ OFCHECK(meas.setPixelSpacing("0.1\\0.1").good());
+ OFCHECK(meas.setSliceThickness("1.0").good());
+ OFCHECK(meas.setSpacingBetweenSlices("0.05").good());
+
+ FGPlanePosPatient planpo;
+ OFCHECK(planpo.setImagePositionPatient("0.0", "0.0", "0.0").good());
+
+ FGPlaneOrientationPatient planor;
+ OFCHECK(planor.setImageOrientationPatient("1.0", "0.0", "0.0", "0.0", "1.0", "0.0").good());
+
+ OFCHECK(seg->addForAllFrames(meas).good());
+ OFCHECK(seg->addForAllFrames(planpo).good());
+ OFCHECK(seg->addForAllFrames(planor).good());
+}
+
+template<typename T>
+static void addFrames(DcmSegmentation* seg, const Uint8 bitsAllocated)
+{
+ if (!seg)
+ return;
+
+ FGFrameContent* fg = new FGFrameContent();
+ OFCHECK(fg);
+ fg->setStackID("1");
+ if (fg)
+ {
+ for (Uint16 frameNo = 1; frameNo <= NUM_FRAMES; frameNo++)
+ {
+ OFCHECK(fg->setFrameAcquisitionNumber(frameNo).good());
+ OFCHECK(fg->setFrameReferenceDateTime("20190816092557").good());
+ OFCHECK(fg->setFrameAcquisitionDateTime("20190816092557").good());
+ OFCHECK(fg->setFrameAcquisitionDuration(0.001).good());
+ OFCHECK(fg->setInStackPositionNumber(frameNo).good());
+ OFCHECK(fg->setDimensionIndexValues(1, 0).good());
+ OFCHECK(fg->setDimensionIndexValues(frameNo, 1).good());
+ OFVector<FGBase*> groups;
+ groups.push_back(fg);
+ T* data = new T[NUM_PIXELS_PER_FRAME];
+ Uint32 max_value = (bitsAllocated == 16 ? 65535 : 256);
+ for (Uint32 i = 0; i < NUM_PIXELS_PER_FRAME; ++i)
+ {
+ data[i] = OFstatic_cast(T, (NUM_PIXELS_PER_FRAME * (frameNo - 1) + i) % max_value);
+ }
+ OFVector<FGBase*> perFrameFGs;
+ perFrameFGs.push_back(fg);
+ OFCHECK(seg->addFrame<T>(data, frameNo, perFrameFGs).good());
+ delete[] data;
+ }
+ }
+ delete fg;
+}
+
+static void addSegments(DcmSegmentation *seg, const Uint8 bitsAllocated)
+{
+ for (Uint32 i = 0; i < ((bitsAllocated == 16) ? 65535u : 255u); i++)
+ {
+ DcmSegment* segment = NULL;
+ CodeSequenceMacro category("85756007", "SCT", "Tissue");
+ CodeSequenceMacro propType("51114001", "SCT", "Artery");
+
+ OFCHECK(DcmSegment::create(segment, "SEGLABEL", category, propType, DcmSegTypes::SAT_AUTOMATIC, "OC_DUMMY")
+ .good());
+ OFCHECK(segment != OFnullptr);
+ Uint16 segno = OFstatic_cast(Uint16, i);
+ OFCHECK(seg->addSegment(segment, segno).good());
+ }
+}
+
+
+static void addDimensions(DcmSegmentation* seg)
+{
+ if (!seg)
+ return;
+ IODMultiframeDimensionModule& dims = seg->getDimensions();
+ OFCHECK(dims.addDimensionIndex(
+ DCM_StackID, "2.25.30855560781715986879861690673941231222", DCM_FrameContentSequence, "STACK_DIM")
+ .good());
+ OFCHECK(dims.addDimensionIndex(DCM_InStackPositionNumber,
+ "2.25.30855560781715986879861690673941231222",
+ DCM_FrameContentSequence,
+ "STACK_DIM")
+ .good());
+ OFunique_ptr<IODMultiframeDimensionModule::DimensionOrganizationItem> org(
+ new IODMultiframeDimensionModule::DimensionOrganizationItem);
+ if (org)
+ {
+ org->setDimensionOrganizationUID("2.25.30855560781715986879861690673941231222");
+ dims.getDimensionOrganizationSequence().push_back(org.release());
+ }
+}
+
+
+static void checkCreatedObject(DcmDataset* dset, const Uint8 bits_allocated, const DcmSegTypes::E_SegmentationLabelmapColorModel cm)
+{
+ // Check imaging parameters
+ Uint16 uint16;
+ OFString str;
+ OFCHECK(dset->findAndGetUint16(DCM_BitsAllocated, uint16).good());
+ OFCHECK(uint16 == bits_allocated);
+ OFCHECK(dset->findAndGetUint16(DCM_BitsStored, uint16).good());
+ OFCHECK(uint16 == bits_allocated);
+ OFCHECK(dset->findAndGetUint16(DCM_HighBit, uint16).good());
+ OFCHECK(uint16 == bits_allocated - 1);
+ OFCHECK(dset->findAndGetUint16(DCM_SamplesPerPixel, uint16).good());
+ OFCHECK(uint16 == 1);
+ OFCHECK(dset->findAndGetUint16(DCM_PixelRepresentation, uint16).good());
+ OFCHECK(uint16 == 0);
+ OFCHECK(dset->findAndGetOFString(DCM_PhotometricInterpretation, str).good());
+ if (cm == DcmSegTypes::SLCM_MONOCHROME2)
+ {
+ OFCHECK(str == "MONOCHROME2");
+ }
+ else
+ {
+ OFCHECK(str == "PALETTE COLOR");
+ checkPalette(dset, bits_allocated);
+ }
+ Sint32 numFrames = 0;
+ OFCHECK(dset->findAndGetSint32(DCM_NumberOfFrames, numFrames).good());
+ OFCHECK(numFrames > 0);
+ OFCHECK(OFstatic_cast(Uint16, numFrames) == NUM_FRAMES);
+ OFCHECK(dset->findAndGetUint16(DCM_Rows, uint16).good());
+ OFCHECK(uint16 == NUM_ROWS);
+ OFCHECK(dset->findAndGetUint16(DCM_Columns, uint16).good());
+ OFCHECK(uint16 == NUM_COLS);
+ OFCHECK(dset->findAndGetOFString(DCM_SegmentationType, str).good());
+ OFCHECK(DcmSegTypes::OFString2Segtype(str) == DcmSegTypes::ST_LABELMAP);
+
+ // Check pixel data
+ if (bits_allocated == 8)
+ {
+ const Uint8* pixData = NULL;
+ OFCHECK(dset->findAndGetUint8Array(DCM_PixelData, pixData).good());
+ OFCHECK(pixData != NULL);
+ if (pixData)
+ {
+ Uint16 max_value = 256;
+ Uint32 numPixels = NUM_ROWS * NUM_COLS * NUM_FRAMES;
+ for (Uint32 i = 0; i < numPixels; i++)
+ {
+ OFCHECK(pixData[i] == OFstatic_cast(Uint8, i % max_value));
+ }
+ }
+ // pixData contains only reference, no need to delete
+ }
+ else if (bits_allocated == 16)
+ {
+ const Uint16* pixData = NULL;
+ OFCHECK(dset->findAndGetUint16Array(DCM_PixelData, pixData).good());
+ OFCHECK(pixData != NULL);
+ if (pixData)
+ {
+ for (Uint32 i = 0; i < NUM_PIXELS_PER_FRAME * numFrames; i++)
+ {
+ OFCHECK(pixData[i] == OFstatic_cast(Uint16, i % 65535));
+ // report expected and actual value in case of mismatch
+ if (pixData[i] != OFstatic_cast(Uint16, i % 65535))
+ {
+ DCMSEG_DEBUG("Expected at index " << i << ": " << OFstatic_cast(Uint16, i % 65535) << ", actual value: " << pixData[i]);
+ }
+ }
+ }
+ // pixData contains only reference, no need to delete
+ }
+
+ // check segments
+ DcmSequenceOfItems* seq = NULL;
+ OFCHECK(dset->findAndGetSequence(DCM_SegmentSequence, seq).good());
+ OFCHECK(seq != NULL);
+ if (seq)
+ {
+ OFCHECK(seq->card() == ((bits_allocated == 16) ? 65535u : 255u));
+ }
+ // check that there is no Segmentation FG
+ DcmElement *fgSeq = NULL;
+ OFCHECK(dset->findAndGetElement(DCM_SegmentIdentificationSequence, fgSeq, OFTrue /* search into sub */).bad());
+}
+
+static void addPaletteAndICCProfile(DcmSegmentation* seg, const Uint8 bitsAllocated)
+{
+ if (bitsAllocated == 8)
+ {
+ IODPaletteColorLUTModule& pal8 = seg->getPaletteColorLUT();
+ OFCHECK(pal8.setRedPaletteColorLookupTableDescriptor(255, 0, 8).good());
+ OFCHECK(pal8.setGreenPaletteColorLookupTableDescriptor(255, 0, 8).good());
+ OFCHECK(pal8.setBluePaletteColorLookupTableDescriptor(255, 0, 8).good());
+ // re-use the same data for all entries
+ const Uint8 MAX_8BIT_ENTRIES = 255;
+ Uint8* data = new Uint8[MAX_8BIT_ENTRIES];
+ for (Uint16 i = 0; i < MAX_8BIT_ENTRIES; i++)
+ {
+ data[i] = OFstatic_cast(Uint8, i);
+ }
+ OFCHECK(pal8.setRedPaletteColorLookupTableData(data, MAX_8BIT_ENTRIES).good());
+ OFCHECK(pal8.setGreenPaletteColorLookupTableData(data, MAX_8BIT_ENTRIES).good());
+ OFCHECK(pal8.setBluePaletteColorLookupTableData(data, MAX_8BIT_ENTRIES).good());
+ delete [] data;
+ }
+ else if (bitsAllocated == 16)
+ {
+ IODPaletteColorLUTModule& pal16= seg->getPaletteColorLUT();
+ OFCHECK(pal16.setRedPaletteColorLookupTableDescriptor(65535, 0, 16).good());
+ OFCHECK(pal16.setGreenPaletteColorLookupTableDescriptor(65535, 0, 16).good());
+ OFCHECK(pal16.setBluePaletteColorLookupTableDescriptor(65535, 0, 16).good());
+ // re-use the same data for all entries
+ Uint16* data = new Uint16[65536];
+ for (Uint16 i = 0; i < 65535u; i++) // TODO
+ {
+ data[i] = i;
+ }
+ OFCHECK(pal16.setRedPaletteColorLookupTableData(data, 65535).good());
+ OFCHECK(pal16.setGreenPaletteColorLookupTableData(data, 65535).good());
+ OFCHECK(pal16.setBluePaletteColorLookupTableData(data, 65535).good());
+ delete [] data;
+ }
+ else
+ {
+ OFCHECK_FAIL("Unsupported value for bitsAllocated");
+ return;
+ }
+ // Palette Color LUT Module requires ICC profile information.
+ // Create ICC profile dummy data which is definitely not a valid ICC profile,
+ // but should be sufficient for testing purposes.
+ const size_t ICC_LENGTH = 256; // length of ICC profile in bytes
+ Uint8* iccProfile = new Uint8[ICC_LENGTH];
+ for (size_t i = 0; i < ICC_LENGTH; i++)
+ {
+ iccProfile[i] = OFstatic_cast(Uint8, i);
+ }
+ OFCHECK(seg->getICCProfile().setICCProfile(iccProfile, ICC_LENGTH, OFTrue /* check */).good());
+ OFCHECK(seg->getICCProfile().setColorSpace("SRGB", OFTrue /* check */).good());
+ delete[] iccProfile;
+}
+
+static void checkPalette(DcmDataset* dset, const Uint8 bitsAllocated)
+{
+ if (bitsAllocated == 8)
+ {
+ Uint8 MAX_ENTRIES_8_BIT = 255;
+ IODPaletteColorLUTModule pal8;
+ OFCHECK(pal8.read(*dset).good());
+ Uint16 numEntries, firstEntry, bits;
+ OFCHECK(pal8.getRedPaletteColorLookupTableDescriptor(numEntries, 0).good());
+ OFCHECK(pal8.getRedPaletteColorLookupTableDescriptor(firstEntry, 1).good());
+ OFCHECK(pal8.getRedPaletteColorLookupTableDescriptor(bits, 2).good());
+ OFCHECK(numEntries == 255);
+ OFCHECK(firstEntry == 0);
+ OFCHECK(bits == bitsAllocated);
+ OFCHECK(pal8.getGreenPaletteColorLookupTableDescriptor(numEntries, 0).good());
+ OFCHECK(pal8.getGreenPaletteColorLookupTableDescriptor(firstEntry, 1).good());
+ OFCHECK(pal8.getGreenPaletteColorLookupTableDescriptor(bits, 2).good());
+ OFCHECK(numEntries == MAX_ENTRIES_8_BIT);
+ OFCHECK(firstEntry == 0);
+ OFCHECK(bits == bitsAllocated);
+ OFCHECK(pal8.getBluePaletteColorLookupTableDescriptor(numEntries, 0).good());
+ OFCHECK(pal8.getBluePaletteColorLookupTableDescriptor(firstEntry, 1).good());
+ OFCHECK(pal8.getBluePaletteColorLookupTableDescriptor(bits, 2).good());
+ OFCHECK(numEntries == MAX_ENTRIES_8_BIT);
+ OFCHECK(firstEntry == 0);
+ OFCHECK(bits == bitsAllocated);
+
+ const Uint8* redData = NULL;
+ const Uint8* greenData = NULL;
+ const Uint8* blueData = NULL;
+ unsigned long numEntriesRed, numEntriesGreen, numEntriesBlue;
+ OFCHECK(pal8.getRedPaletteColorLookupTableData(redData, numEntriesRed).good());
+ OFCHECK(pal8.getGreenPaletteColorLookupTableData(greenData, numEntriesGreen).good());
+ OFCHECK(pal8.getBluePaletteColorLookupTableData(blueData, numEntriesBlue).good());
+ OFCHECK(numEntriesRed == MAX_ENTRIES_8_BIT);
+ OFCHECK(numEntriesBlue == MAX_ENTRIES_8_BIT);
+ OFCHECK(numEntriesGreen == MAX_ENTRIES_8_BIT);
+ OFCHECK(redData != NULL);
+ OFCHECK(greenData != NULL);
+ OFCHECK(blueData != NULL);
+ if (redData && greenData && blueData)
+ {
+ for (Uint32 i = 0; i < MAX_ENTRIES_8_BIT; i++)
+ {
+ OFCHECK(redData[i] == OFstatic_cast(Uint8, i));
+ OFCHECK(greenData[i] == OFstatic_cast(Uint8, i));
+ OFCHECK(blueData[i] == OFstatic_cast(Uint8, i));
+ }
+ }
+ delete[] redData;
+ delete[] greenData;
+ delete[] blueData;
+ }
+ else if (bitsAllocated == 16)
+ {
+ IODPaletteColorLUTModule pal16;
+ OFCHECK(pal16.read(*dset).good());
+ Uint16 numEntries, firstEntry, bits;
+ OFCHECK(pal16.getRedPaletteColorLookupTableDescriptor(numEntries, 0).good());
+ OFCHECK(pal16.getRedPaletteColorLookupTableDescriptor(firstEntry, 1).good());
+ OFCHECK(pal16.getRedPaletteColorLookupTableDescriptor(bits, 2).good());
+ OFCHECK(numEntries == 65535);
+ OFCHECK(firstEntry == 0);
+ OFCHECK(bits == bitsAllocated);
+ OFCHECK(pal16.getGreenPaletteColorLookupTableDescriptor(numEntries, 0).good());
+ OFCHECK(pal16.getGreenPaletteColorLookupTableDescriptor(firstEntry, 1).good());
+ OFCHECK(pal16.getGreenPaletteColorLookupTableDescriptor(bits, 2).good());
+ OFCHECK(numEntries == 65535);
+ OFCHECK(firstEntry == 0);
+ OFCHECK(bits == bitsAllocated);
+ OFCHECK(pal16.getBluePaletteColorLookupTableDescriptor(numEntries, 0).good());
+ OFCHECK(pal16.getBluePaletteColorLookupTableDescriptor(firstEntry, 1).good());
+ OFCHECK(pal16.getBluePaletteColorLookupTableDescriptor(bits, 2).good());
+ OFCHECK(numEntries == 65535);
+ OFCHECK(firstEntry == 0 );
+ OFCHECK(bits == bitsAllocated);
+
+ const Uint16* redData = NULL;
+ const Uint16* greenData = NULL;
+ const Uint16* blueData = NULL;
+ unsigned long numEntriesRed, numEntriesGreen, numEntriesBlue;
+ OFCHECK(pal16.getRedPaletteColorLookupTableData(redData, numEntriesRed).good());
+ OFCHECK(pal16.getGreenPaletteColorLookupTableData(greenData, numEntriesGreen).good());
+ OFCHECK(pal16.getBluePaletteColorLookupTableData(blueData, numEntriesBlue).good());
+ OFCHECK(numEntriesRed == 65535);
+ OFCHECK(numEntriesBlue == 65535);
+ OFCHECK(numEntriesGreen == 65535);
+ OFCHECK(redData != NULL);
+ OFCHECK(greenData != NULL);
+ OFCHECK(blueData != NULL);
+ if (redData && greenData && blueData)
+ {
+ for (Uint32 i = 0; i < 65535; i++)
+ {
+ OFCHECK(redData[i] == i);
+ OFCHECK(greenData[i] == i);
+ OFCHECK(blueData[i] == i);
+ }
+ }
+ }
+}
+
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmseg
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Test for packing and unpacking binary segmentation pixel data
+ *
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/dcmseg/segdoc.h"
+#include "dcmtk/dcmseg/segment.h"
+#include "dcmtk/dcmseg/segutils.h"
+#include "dcmtk/ofstd/oftest.h"
+
+#include "dcmtk/dcmfg/fgfracon.h"
+#include "dcmtk/dcmfg/fgpixmsr.h"
+#include "dcmtk/dcmfg/fgplanor.h"
+#include "dcmtk/dcmfg/fgplanpo.h"
+#include "dcmtk/dcmfg/fgseg.h"
+#include "dcmtk/dcmiod/iodmacro.h"
+#include "dcmtk/dcmdata/dcxfer.h"
+#include "dcmtk/dcmdata/dcdict.h"
+#include "dcmtk/ofstd/ofmem.h"
+#include "dcmtk/ofstd/oftempf.h"
+#include "dcmtk/ofstd/oftest.h"
+//#include <iostream>
+
+static const Uint16 NUM_ROWS = 512;
+static const Uint16 NUM_COLS = 512;
+// 17388
+static const Uint16 NUM_FRAMES = 17000;
+static const size_t NUM_PIXELS_PER_FRAME = NUM_COLS * NUM_ROWS;
+
+static OFString EXPECTED_DUMP;
+
+static void prepareExpectedDump();
+static DcmSegmentation* create();
+static void setGenericValues(DcmSegmentation* seg);
+static void addSharedFGs(DcmSegmentation* seg);
+static void addFrames(DcmSegmentation* seg);
+static void addDimensions(DcmSegmentation* seg);
+static OFString write(DcmSegmentation* seg, DcmDataset& ds);
+
+OFTEST(dcmseg_packing)
+{
+ // Make sure data dictionary is loaded
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK_FAIL("no data dictionary loaded, check environment variable: " DCM_DICT_ENVIRONMENT_VARIABLE);
+ return;
+ }
+
+ // Creation
+ std::cout << "Creating segmentation" << std::endl;
+ DcmSegmentation* seg = create();
+ std::cout << "Setting generic values" << std::endl;
+ setGenericValues(seg);
+ std::cout << "Adding shared functional groups" << std::endl;
+ addSharedFGs(seg);
+ std::cout << "Adding frames" << std::endl;
+ addFrames(seg);
+ std::cout << "Adding dimensions" << std::endl;
+ addDimensions(seg);
+
+ // Write to dataset and compare its dump with expected result
+ DcmFileFormat dcmff;
+ DcmDataset* ds = dcmff.getDataset();
+
+ // Save to disk, and re-load to test import
+ seg->getFunctionalGroups().setCheckOnWrite(OFFalse);
+ seg->getFunctionalGroups().setUseThreads(16);
+ seg->setCheckDimensionsOnWrite(OFFalse);
+ OFString temp_fn = "/tmp/test.dcm";
+ std::cout << "Writing segmentation to file: " << temp_fn << std::endl;
+ OFCHECK(seg->saveFile(temp_fn.c_str(), EXS_LittleEndianExplicit).good());
+ std::cout << "Temporary file created: " << temp_fn << std::endl;
+ delete seg;
+}
+
+static DcmSegmentation* create()
+{
+ IODGeneralEquipmentModule::EquipmentInfo eq("Open Connections", "OC CT", "4711", "0.1");
+ ContentIdentificationMacro ci("1", "LABEL", "DESCRIPTION", "Doe^John");
+ DcmSegmentation* seg = NULL;
+ OFCondition result;
+ DcmSegmentation::createBinarySegmentation(seg, NUM_ROWS, NUM_COLS , eq, ci);
+ OFCHECK(result.good());
+ OFCHECK(seg != OFnullptr);
+ return seg;
+}
+
+static void setGenericValues(DcmSegmentation* seg)
+{
+ if (!seg)
+ return;
+ OFCHECK(seg->getPatient().setPatientName("Bond^James").good());
+ OFCHECK(seg->getPatient().setPatientID("007").good());
+ OFCHECK(seg->getPatient().setPatientBirthDate("19771007").good());
+ OFCHECK(seg->getStudy().setStudyDate("20190801").good());
+ OFCHECK(seg->getStudy().setStudyTime("120000").good());
+ OFCHECK(seg->getStudy().setStudyID("1").good());
+ OFCHECK(seg->getPatientStudy().setPatientAge("040Y").good());
+ OFCHECK(seg->getSeries().setSeriesDescription("Test Description").good());
+ OFCHECK(seg->getSeries().setSeriesNumber("1").good());
+ OFCHECK(seg->getSeries().setPatientPosition("HFS").good());
+
+ // Those values are usually computed automatically. UIDS are generated and date/times are set to current values.
+ // But in order to compare the "old" dump with the freshly created image attributes, we set some values manually,
+ // so that they are not overwritten with new, automatically created values later.
+ OFCHECK(seg->getStudy().setStudyInstanceUID("1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811").good());
+ OFCHECK(seg->getFrameOfReference().setFrameOfReferenceUID("2.25.30853397773651184949181049330553108086").good());
+ OFCHECK(seg->getSeries().setSeriesInstanceUID("1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812").good());
+ OFCHECK(seg->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good());
+ OFCHECK(seg->getGeneralImage().setContentDate("20190927").good());
+ OFCHECK(seg->getGeneralImage().setContentTime("153857").good());
+ OFCHECK(seg->getGeneralImage().setContentTime("153857").good());
+}
+
+
+static void addSharedFGs(DcmSegmentation* seg)
+{
+ if (!seg)
+ return;
+
+ FGPixelMeasures meas;
+ OFCHECK(meas.setPixelSpacing("0.1\\0.1").good());
+ OFCHECK(meas.setSliceThickness("1.0").good());
+ OFCHECK(meas.setSpacingBetweenSlices("0.05").good());
+
+ FGPlanePosPatient planpo;
+ OFCHECK(planpo.setImagePositionPatient("0.0", "0.0", "0.0").good());
+
+ FGPlaneOrientationPatient planor;
+ OFCHECK(planor.setImageOrientationPatient("1.0", "0.0", "0.0", "0.0", "1.0", "0.0").good());
+
+ OFCHECK(seg->addForAllFrames(meas).good());
+ OFCHECK(seg->addForAllFrames(planpo).good());
+ OFCHECK(seg->addForAllFrames(planor).good());
+}
+
+static void addFrames(DcmSegmentation* seg)
+{
+ if (!seg)
+ return;
+
+ DcmSegment* segment = NULL;
+ CodeSequenceMacro category("85756007", "SCT", "Tissue");
+ CodeSequenceMacro propType("51114001", "SCT", "Artery");
+
+ OFCHECK(DcmSegment::create(segment, "SEGLABEL", category, propType, DcmSegTypes::SAT_AUTOMATIC, "OC_DUMMY")
+ .good());
+ OFCHECK(segment != OFnullptr);
+ Uint16 forget;
+ OFCHECK(seg->addSegment(segment, forget).good());
+ // Segmentation FG is created automatically
+ FGFrameContent* fg = new FGFrameContent();
+ OFCHECK(fg);
+ for (Uint16 frameNo = 1; frameNo <= NUM_FRAMES; frameNo++)
+ {
+ fg->setStackID("1");
+
+ OFCHECK(fg->setFrameAcquisitionNumber(frameNo).good());
+ OFCHECK(fg->setFrameReferenceDateTime("20190816092557").good());
+ OFCHECK(fg->setFrameAcquisitionDateTime("20190816092557").good());
+ OFCHECK(fg->setFrameAcquisitionDuration(0.001).good());
+ OFCHECK(fg->setInStackPositionNumber(frameNo).good());
+ OFCHECK(fg->setDimensionIndexValues(1, 0).good());
+ OFCHECK(fg->setDimensionIndexValues(frameNo, 1).good());
+ OFVector<FGBase*> groups;
+ groups.push_back(fg);
+
+ Uint8* data = new Uint8[NUM_PIXELS_PER_FRAME];
+ for (size_t i = 0; i < NUM_PIXELS_PER_FRAME; ++i)
+ {
+ data[i] = 1;
+ }
+ OFVector<FGBase*> perFrameFGs;
+ perFrameFGs.push_back(fg);
+ OFCHECK(seg->addFrame(data, forget, perFrameFGs).good());
+ delete[] data;
+ }
+ delete fg;
+}
+
+static void addDimensions(DcmSegmentation* seg)
+{
+ if (!seg)
+ return;
+ IODMultiframeDimensionModule& dims = seg->getDimensions();
+ OFCHECK(dims.addDimensionIndex(
+ DCM_StackID, "2.25.30855560781715986879861690673941231222", DCM_FrameContentSequence, "STACK_DIM")
+ .good());
+ OFCHECK(dims.addDimensionIndex(DCM_InStackPositionNumber,
+ "2.25.30855560781715986879861690673941231222",
+ DCM_FrameContentSequence,
+ "STACK_DIM")
+ .good());
+ OFunique_ptr<IODMultiframeDimensionModule::DimensionOrganizationItem> org(
+ new IODMultiframeDimensionModule::DimensionOrganizationItem);
+ if (org)
+ {
+ org->setDimensionOrganizationUID("2.25.30855560781715986879861690673941231222");
+ dims.getDimensionOrganizationSequence().push_back(org.release());
+ }
+}
+
+static OFString write(DcmSegmentation* seg, DcmDataset& ds)
+{
+ OFCondition result = seg->writeDataset(ds);
+ OFCHECK(result.good());
+
+ return "";
+}
/*
*
- * Copyright (C) 2019-2024, OFFIS e.V.
+ * Copyright (C) 2019-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofmem.h"
#include "dcmtk/ofstd/oftempf.h"
#include "dcmtk/ofstd/oftest.h"
+//#include <iostream>
static const Uint8 NUM_ROWS = 10;
static const Uint8 NUM_COLS = 10;
OFCHECK(seg->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good());
OFCHECK(seg->getGeneralImage().setContentDate("20190927").good());
OFCHECK(seg->getGeneralImage().setContentTime("153857").good());
+ OFCHECK(seg->getGeneralImage().setContentTime("153857").good());
}
+
static void addSharedFGs(DcmSegmentation* seg)
{
if (!seg)
if (!seg)
return;
- FGSegmentation* fg_seg = new FGSegmentation();
+ // Segmentation FG is created automatically
FGFrameContent* fg = new FGFrameContent();
- OFCHECK(fg && fg_seg);
+ OFCHECK(fg);
fg->setStackID("1");
if (fg)
{
{
data[i] = i;
}
- OFCHECK(fg_seg->setReferencedSegmentNumber(frameNo).good());
OFVector<FGBase*> perFrameFGs;
perFrameFGs.push_back(fg);
- perFrameFGs.push_back(fg_seg);
- OFCHECK(seg->addFrame(data, frameNo, perFrameFGs).good());
+ OFCHECK(seg->addFrame<Uint8>(data, frameNo, perFrameFGs).good());
delete[] data;
}
}
delete fg;
- delete fg_seg;
}
static void addDimensions(DcmSegmentation* seg)
OFCHECK(fg != NULL);
OFCHECK(perFrame == OFFalse);
- const DcmIODTypes::Frame* frame = concat->getFrame(0);
+ const DcmIODTypes::Frame<Uint8>* frame = OFstatic_cast(const DcmIODTypes::Frame<Uint8>*, concat->getFrame(0));
OFCHECK(frame != OFnullptr);
- OFCHECK(frame->pixData != OFnullptr);
- OFCHECK(OFstatic_cast(Uint8, frame->length) == NUM_PIXELS_PER_FRAME);
- for (size_t pix = 0; pix < frame->length; pix++)
+ OFCHECK(frame->m_pixData != OFnullptr);
+ OFCHECK(OFstatic_cast(Uint8, frame->getLengthInBytes()) == NUM_PIXELS_PER_FRAME);
+ for (size_t pix = 0; pix < frame->getLengthInBytes(); pix++)
{
- OFCHECK(frame->pixData[pix] == pix);
+ OFCHECK(frame->m_pixData[pix] == pix);
}
delete concat;
}
EXPECTED_DUMP += "(fffe,e0dd) na (SequenceDelimitationItem for re-encod.) # 0, 0 SequenceDelimitationItem\n";
EXPECTED_DUMP += "(0062,000e) US 255 # 2, 1 MaximumFractionalValue\n";
EXPECTED_DUMP += "(0062,0010) CS [OCCUPANCY] # 10, 1 SegmentationFractionalType\n";
+ EXPECTED_DUMP += "(0062,0013) CS [UNDEFINED] # 10, 1 SegmentsOverlap\n";
EXPECTED_DUMP += "(0070,0080) CS [LABEL] # 6, 1 ContentLabel\n";
EXPECTED_DUMP += "(0070,0081) LO [DESCRIPTION] # 12, 1 ContentDescription\n";
EXPECTED_DUMP += "(0070,0084) PN [Doe^John] # 8, 1 ContentCreatorName\n";
/*
*
- * Copyright (C) 2015-2024, OFFIS e.V.
+ * Copyright (C) 2015-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-#include "dcmtk/dcmiod/iodtypes.h"
#include "dcmtk/dcmseg/segutils.h"
+#include "dcmtk/dcmseg/segtypes.h"
#include "dcmtk/ofstd/oftest.h"
#include "dcmtk/ofstd/ofstd.h"
+#include "dcmtk/ofstd/oftime.h" // For debugByte2Bin
+#include <iostream>
#define bufLen 4
// Check whether packing of sparse frames into binary packed frames works correctly
OFTEST(dcmseg_packBinaryFrame)
{
-
// Check whether the following statically defined frames are packed correctly
Uint8 sparseFrame1[8] = {1, 1, 1, 1, 0, 0, 0, 0};
- DcmIODTypes::Frame* packed = DcmSegUtils::packBinaryFrame(sparseFrame1, 4, 2);
+ DcmIODTypes::Frame<Uint8>* packed = DcmSegUtils::packBinaryFrame(sparseFrame1, 4, 2);
OFCHECK(packed != NULL);
- OFCHECK(packed->length == 1);
- OFCHECK_MSG(packed->pixData[0] == 0b00001111, OFString("Expected 0b00001111, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[0]));
+ OFCHECK(packed->getLengthInBytes() == 1);
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[0] == 0b00001111, OFString("Expected 0b00001111, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[0]));
delete packed;
Uint8 sparseFrame2[8] = {1, 0, 1, 0, 1, 0, 1, 0};
packed = DcmSegUtils::packBinaryFrame(sparseFrame2, 4, 2);
OFCHECK(packed != NULL);
- OFCHECK(packed->length == 1);
- OFCHECK_MSG(packed->pixData[0] == 0b01010101, OFString("Expected 0b01010101, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[0]));
+ OFCHECK(packed->getLengthInBytes() == 1);
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[0] == 0b01010101, OFString("Expected 0b01010101, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[0]));
delete packed;
// Now try the that is larger than a byte and not a multiple of 8, with every third pixel set to 1
Uint8 sparseFrame3[15] = {0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1};
packed = DcmSegUtils::packBinaryFrame(sparseFrame3, 5, 3);
OFCHECK(packed != NULL);
- OFCHECK(packed->length == 2);
- OFCHECK_MSG(packed->pixData[0] == 0b00100100, OFString("Expected 0b00100100, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[0]));
- OFCHECK_MSG(packed->pixData[1] == 0b01001001, OFString("Expected 0b01001001, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[1]));
+ OFCHECK(packed->getLengthInBytes() == 2);
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[0] == 0b00100100, OFString("Expected 0b00100100, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[0]));
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[1] == 0b01001001, OFString("Expected 0b01001001, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[1]));
delete packed;
// Now the same but with every 5th pixel set to 1, and rows=7 and cols=5
}
packed = DcmSegUtils::packBinaryFrame(sparseFrame4, 7, 5);
OFCHECK(packed != NULL);
- OFCHECK(packed->length == 5);
- OFCHECK_MSG(packed->pixData[0] == 0b00100001, OFString("Expected 0b00100001, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[0]));
- OFCHECK_MSG(packed->pixData[1] == 0b10000100, OFString("Expected 0b10000100, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[1]));
- OFCHECK_MSG(packed->pixData[2] == 0b00010000, OFString("Expected 0b00010000, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[2]));
- OFCHECK_MSG(packed->pixData[3] == 0b01000010, OFString("Expected 0b01000010, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[3]));
- OFCHECK_MSG(packed->pixData[4] == 0b00000000, OFString("Expected 0b00000000, got ") + DcmSegUtils::debugByte2Bin(packed->pixData[4]));
+ OFCHECK(packed->getLengthInBytes() == 5);
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[0] == 0b00100001, OFString("Expected 0b00100001, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[0]));
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[1] == 0b10000100, OFString("Expected 0b10000100, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[1]));
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[2] == 0b00010000, OFString("Expected 0b00010000, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[2]));
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[3] == 0b01000010, OFString("Expected 0b01000010, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[3]));
+ OFCHECK_MSG(OFstatic_cast(Uint8*, packed->getPixelData())[4] == 0b00000000, OFString("Expected 0b00000000, got ") + DcmSegUtils::debugByte2Bin( OFstatic_cast(Uint8*, packed->getPixelData())[4]));
+ delete packed;
// In 1000 iterations create sparse frames and pack them. Check whether the
// packed frame is correct. This is not bullet proof but we use the same addressing
- // as in the packing/unpacking code to make sure we address the right bit.
+ // as in the packing/unpacking code to make sure we address the correct bit.
// Use a random number of cols and rows (each between 1 and 100).
// If the packed frame is not correct, the test fails.
- unsigned int now = OFstatic_cast(unsigned int, time(NULL));
+ OFTime tm;
for (unsigned int i = 0; i < 1000; i++)
{
+ unsigned int now = OFstatic_cast(unsigned int, time(NULL));
Uint16 cols = OFrand_r(now) % 100 + 1;
Uint16 rows = OFrand_r(now) % 100 + 1;
Uint16 pixelCount = cols * rows;
// Create a random sparse frame
for (unsigned int j = 0; j < pixelCount; j++)
{
- sparseFrame[j] = OFrand_r(now) % 2;
+ tm.setCurrentTime();
+ unsigned int micro = tm.getMicroSecond();
+ sparseFrame[j] = OFrand_r(micro) % 2;
}
-
// Pack the frame
- DcmIODTypes::Frame* packedFrame = DcmSegUtils::packBinaryFrame(sparseFrame, rows, cols);
+ DcmIODTypes::Frame<Uint8>* packedFrame = DcmSegUtils::packBinaryFrame(sparseFrame, rows, cols);
OFCHECK(packedFrame != NULL);
// Check the result
Uint32 byteIndex = j / 8;
Uint32 bitIndex = j % 8;
Uint8 mask = 1 << bitIndex;
- if ((sparseFrame[j] != 0) != ((packedFrame->pixData[byteIndex] & mask) != 0))
+ Uint8 currentByte = OFstatic_cast(Uint8*, packedFrame->getPixelData())[byteIndex];
+ // Check whether the bit at position j is set correctly
+ if ((sparseFrame[j] == 0) != ((currentByte & mask) == 0))
{
OFCHECK_FAIL("Failed for row " << j / cols << " and column " << j % cols);
}
}
+ // Clean up
delete[] sparseFrame;
delete packedFrame;
}
Uint8* sparseFrame = new Uint8[pixelCount];
OFCHECK(sparseFrame != NULL);
- DcmIODTypes::Frame* packed;
- DcmIODTypes::Frame* unpacked;
+ DcmIODTypes::FrameBase* packed;
+ DcmIODTypes::FrameBase* unpacked;
// Create a random sparse frame
for (unsigned int j = 0; j < pixelCount; j++)
// Pack and unpack the frame
packed = DcmSegUtils::packBinaryFrame(sparseFrame, rows, cols);
OFCHECK(packed != NULL);
- unpacked = DcmSegUtils::unpackBinaryFrame(packed, rows, cols);
+ unpacked = DcmSegUtils::unpackBinaryFrame(OFstatic_cast(DcmIODTypes::Frame<Uint8>*, packed), rows, cols);
OFCHECK(unpacked != NULL);
// Compare the result
- OFCHECK(memcmp(sparseFrame, unpacked->pixData, pixelCount) == 0);
+ OFCHECK(memcmp(sparseFrame, unpacked->getPixelData(), pixelCount) == 0);
delete[] sparseFrame;
delete packed;
Uint8* sparseFrame = new Uint8[pixelCount];
OFCHECK(sparseFrame != NULL);
memset(sparseFrame, 0, pixelCount);
- DcmIODTypes::Frame* packed = DcmSegUtils::packBinaryFrame(sparseFrame, rows, cols);
+ DcmIODTypes::FrameBase* packed = DcmSegUtils::packBinaryFrame(sparseFrame, rows, cols);
OFCHECK(packed != NULL);
- DcmIODTypes::Frame* unpacked = DcmSegUtils::unpackBinaryFrame(packed, rows, cols);
+ DcmIODTypes::FrameBase* unpacked = DcmSegUtils::unpackBinaryFrame(OFstatic_cast(DcmIODTypes::Frame<Uint8>*, packed), rows, cols);
OFCHECK(unpacked != NULL);
- OFCHECK(memcmp(sparseFrame, unpacked->pixData, pixelCount) == 0);
+ OFCHECK(memcmp(sparseFrame, unpacked->getPixelData(), pixelCount) == 0);
delete packed;
delete unpacked;
memset(sparseFrame, 1, pixelCount);
packed = DcmSegUtils::packBinaryFrame(sparseFrame, rows, cols);
OFCHECK(packed != NULL);
- unpacked = DcmSegUtils::unpackBinaryFrame(packed, rows, cols);
+ unpacked = DcmSegUtils::unpackBinaryFrame(OFstatic_cast(DcmIODTypes::Frame<Uint8>*, packed), rows, cols);
OFCHECK(unpacked != NULL);
- OFCHECK(memcmp(sparseFrame, unpacked->pixData, pixelCount) == 0);
+ OFCHECK(memcmp(sparseFrame, unpacked->getPixelData(), pixelCount) == 0);
delete packed;
delete unpacked;
const int cols = 4;
Uint8 sparseFrame1[rows * cols] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
Uint8 sparseFrame2[rows * cols] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
- DcmIODTypes::Frame* packed1 = DcmSegUtils::packBinaryFrame(sparseFrame1, rows, cols);
- DcmIODTypes::Frame* packed2 = DcmSegUtils::packBinaryFrame(sparseFrame2, rows, cols);
+ DcmIODTypes::FrameBase* packed1 = DcmSegUtils::packBinaryFrame(sparseFrame1, rows, cols);
+ DcmIODTypes::FrameBase* packed2 = DcmSegUtils::packBinaryFrame(sparseFrame2, rows, cols);
OFCHECK(packed1 != NULL);
OFCHECK(packed2 != NULL);
- OFVector<DcmIODTypes::Frame*> inputFrames;
+ OFVector<DcmIODTypes::FrameBase*> inputFrames;
inputFrames.push_back(packed1);
inputFrames.push_back(packed2);
// Now concatenate the two frames into a single bit array
OFCHECK_MSG(pixData[0] == 0b11111111, OFString("Expected 0b11111111, got ") + DcmSegUtils::debugByte2Bin(pixData[0]));
OFCHECK_MSG(pixData[1] == 0b11101111, OFString("Expected 0b11101111, got ") + DcmSegUtils::debugByte2Bin(pixData[1]));
OFCHECK_MSG(pixData[2] == 0b11111111, OFString("Expected 0b11111111, got ") + DcmSegUtils::debugByte2Bin(pixData[2]));
+ // avoid memory leaks
+ delete packed1;
+ delete packed2;
+ delete[] pixData;
}
// Test DcmSegUtils::debugByte2Bin()
\section dcmsign_copyright COPYRIGHT
-Copyright (C) 2000-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2000-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \
../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \
../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \
../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \
../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
E_FileReadMode opt_readMode = ERM_autoDetect;
E_TransferSyntax opt_ixfer = EXS_Unknown;
OFBool opt_checkAllStrings = OFFalse;
+#ifdef DCMTK_ENABLE_CHARSET_CONVERSION
OFBool opt_convertToUTF8 = OFFalse;
+#endif
OFConsoleApplication app(OFFIS_CONSOLE_APPLICATION, "Render DICOM SR file and data set to HTML/XHTML", rcsid);
OFCommandLine cmd;
/*
*
- * Copyright (C) 2000-2023, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/*
*
- * Copyright (C) 2003-2024, OFFIS e.V.
+ * Copyright (C) 2003-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/ofstream.h"
#include "dcmtk/ofstd/ofconapp.h"
+#include "dcmtk/ofstd/ofdiag.h"
#ifdef WITH_ZLIB
#include <zlib.h> /* for zlibVersion() */
#define LIBXML_ATTR_FORMAT(fmt,args)
#endif
+// MacOS 15.5 defines some Clang specific pragmas in libxml header files.
+// Suppress warnings caused by these pragmas when compiling with GCC.
+#include DCMTK_DIAGNOSTIC_PUSH
+#include DCMTK_DIAGNOSTIC_IGNORE_CLANG_PRAGMAS_ON_GCC
#include <libxml/parser.h>
-
+#include DCMTK_DIAGNOSTIC_POP
#define SHORTCOL 3
#define LONGCOL 21
<xsd:annotation>
<xsd:documentation xml:lang="en">
XML Schema for DCMTK tools dsr2xml and xml2dsr.
- Copyright (C) 2003-2024, OFFIS e.V. and J. Riesmeier
+ Copyright (C) 2003-2025, OFFIS e.V. and J. Riesmeier
All rights reserved. See COPYRIGHT file for details.
</xsd:documentation>
</xsd:annotation>
</xsd:complexType>
</xsd:element>
<xsd:element name="sex" type="dsr:Sex" minOccurs="0"/>
- <!-- strictly speaking, Patient's Size and Weight belong to the Study IE -->
+ <!-- strictly speaking, Patient's Age, Size and Weight belong to the Study IE -->
+ <xsd:element name="age" type="dsr:AgeString" minOccurs="0"/>
<xsd:element name="size" type="dsr:DecimalString" minOccurs="0"/>
<xsd:element name="weight" type="dsr:DecimalString" minOccurs="0"/>
</xsd:sequence>
</xsd:restriction>
</xsd:simpleType>
+ <xsd:simpleType name="AgeString">
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="[0-9]{3}[DWMY]"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
<xsd:complexType name="PersonName">
<!-- minLength? -->
<xsd:sequence>
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
\endverbatim
+(*) This is not a Storage SOP Class, but used for Real-Time Communication.
+
\subsection dsr2html_character_encoding Character Encoding
The HTML/XHTML encoding is determined automatically from the DICOM attribute
Option \e --convert-to-utf8 can be used to convert the DICOM file or data set
to UTF-8 encoding prior to the rendering to HTML/XHTML format.
+\subsection dsr2html_security Security
+
+Please note that using one of the options \e --css-reference, \e --css-file or
+\e --hyperlink-url-prefix can lead to security issues, as an attacker could
+misuse them to potentially inject dangerous content into the HTML/XHTML output.
+The values passed to these options are not checked, neither the URL and prefix
+nor the content of the specified CSS file.
+
\section dsr2html_logging LOGGING
The level of logging output of the various command line tools and underlying
\section dsr2html_files FILES
<em>\<datadir\>/report.css</em> - Sample Cascading Stylesheet file for HTML
-<em>\<datadir\>/reportx.css</em> - Sample Cascading Stylesheet file for XHTML
+\n<em>\<datadir\>/reportx.css</em> - Sample Cascading Stylesheet file for XHTML
\section dsr2html_see_also SEE ALSO
\section dsr2html_copyright COPYRIGHT
-Copyright (C) 2000-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2000-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
\endverbatim
+(*) This is not a Storage SOP Class, but used for Real-Time Communication.
+
Please note that currently only mandatory and some optional attributes are
supported.
\section dsr2xml_copyright COPYRIGHT
-Copyright (C) 2000-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2000-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
\endverbatim
+(*) This is not a Storage SOP Class, but used for Real-Time Communication.
+
\section dsrdump_logging LOGGING
The level of logging output of the various command line tools and underlying
\section dsrdump_copyright COPYRIGHT
-Copyright (C) 2000-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2000-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
\endverbatim
+(*) This is not a Storage SOP Class, but used for Real-Time Communication.
+
Please note that currently only mandatory and some optional attributes are
supported.
\section xml2dsr_copyright COPYRIGHT
-Copyright (C) 2003-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 2003-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID100_QuantitativeDiagnosticImagingProcedure
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:09 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:43 by J. Riesmeier
*
*/
/** Implementation of DCMR Context Group:
* CID 100 - Quantitative Diagnostic Imaging Procedure.
- * (type: extensible, version: 20230630)
+ * (type: extensible, version: 20250122)
*/
class DCMTK_CMR_EXPORT CID100_QuantitativeDiagnosticImagingProcedure
: public DSRContextGroup
/// (39142-5,LN,"CT perfusion head with contrast IV")
CTPerfusionHeadWithContrastIV,
/// (39632-5,LN,"SPECT brain")
- SPECTBrain,
- /// (RPID5427,RADLEX,"NM head perfusion brain PET-CT AV-45")
- NMHeadPerfusionBrainPET_CT_AV45
+ SPECTBrain
};
/** (default) constructor
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID10013_CTAcquisitionType
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:25 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:57 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID10033_CTReconstructionAlgorithm
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:26 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:58 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID11_AdministrationRoute
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:06 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:40 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID218_QuantitativeImageFeature
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:10 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:44 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID244_Laterality
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:11 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:45 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID247_LateralityLeftRightOnly
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:12 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:45 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID29_AcquisitionModality
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:07 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:41 by J. Riesmeier
*
*/
IntravascularUltrasound,
/// (KER,DCM,"Keratometry")
Keratometry,
- /// (LS,DCM,"Laser Scan")
- LaserScan,
+ /// (LS,DCM,"Laser surface scan")
+ LaserSurfaceScan,
/// (LEN,DCM,"Lensometry")
Lensometry,
/// (MR,DCM,"Magnetic Resonance")
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID4020_PETRadionuclide
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:13 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:46 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID4021_PETRadiopharmaceutical
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:14 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:47 by J. Riesmeier
*
*/
/** Implementation of DCMR Context Group:
* CID 4021 - PET Radiopharmaceutical.
- * (type: extensible, version: 20221201)
+ * (type: extensible, version: 20251111)
*/
class DCMTK_CMR_EXPORT CID4021_PETRadiopharmaceutical
: public DSRContextGroup
_28H1_89Zr,
/// (126713,DCM,"2FA F^18^")
_2FA_F18,
+ /// (C90936,NCIt,"2-Thymidine C^11^")
+ _2Thymidine_C11,
+ /// (771875003,SCT,"3-N-Methylspiperone C^11^")
+ _3NMethylspiperone_C11,
/// (126751,DCM,"7D12 ^89^Zr")
_7D12_89Zr,
/// (126750,DCM,"7E11 ^89^Zr")
CMAbU36_89Zr,
/// (126515,DCM,"cU36 ^89^Zr")
CU36_89Zr,
+ /// (C412822,MSH,"DASB C^11^")
+ DASB_C11,
/// (C96234,NCIt,"DCFBC F^18^")
DCFBC_F18,
- /// (C116352,NCIt,"Piflufolastat F^18^")
- Piflufolastat_F18,
/// (126762,DCM,"Df-[FK](2) ^89^Zr")
DfFK2_89Zr,
/// (126763,DCM,"Df-[FK](2)-3PEG(4) ^89^Zr")
DfFKPEG3_89Zr,
/// (126747,DCM,"DN30 ^89^Zr")
DN30_89Zr,
+ /// (724025002,SCT,"Dotatate Ga^68^")
+ Dotatate_Ga68,
/// (126765,DCM,"DPA-713 ^11^C")
DPA713_11C,
/// (126766,DCM,"DPA-714 ^18^F")
Flumazenil_F18,
/// (424708001,SCT,"Fluorethyltyrosin F^18^")
Fluorethyltyrosin_F18,
+ /// (C62520,NCIt,"Fluoroazomycin arabinoside F^18^")
+ FluoroazomycinArabinoside_F18,
/// (423546004,SCT,"Fluorobenzothiazole F^18^")
Fluorobenzothiazole_F18,
/// (456992002,SCT,"Fluorocholine F^18^")
Fluoromisonidazole_F18,
/// (C2934038,UMLS,"Fluoropropyl-dihydrotetrabenazine F^18^")
FluoropropylDihydrotetrabenazine_F18,
+ /// (764937002,SCT,"Fluorothymidine F^18^")
+ Fluorothymidine_F18,
/// (126707,DCM,"Fluorotriopride F^18^")
Fluorotriopride_F18,
/// (425236000,SCT,"Fluorouracil F^18^")
Germanium_Ge68,
/// (126724,DCM,"Glembatumumab vedotin ^89^Zr")
GlembatumumabVedotin_89Zr,
+ /// (126521,DCM,"Glucose C^11^")
+ Glucose_C11,
/// (129509006,SCT,"Glutamate N^13^")
Glutamate_N13,
/// (126709,DCM,"Glutamine C^11^")
Panitumumab_89Zr,
/// (126728,DCM,"Pegdinetanib ^89^Zr")
Pegdinetanib_89Zr,
+ /// (C148167,NCIt,"Pembrolizumab ^89^Zr")
+ Pembrolizumab_89Zr,
+ /// (C5433257,UMLS,"PI-2620 F^18^")
+ PI2620_F18,
+ /// (C116352,NCIt,"Piflufolastat F^18^")
+ Piflufolastat_F18,
/// (126725,DCM,"Pinatuzumab vedotin ^89^Zr")
PinatuzumabVedotin_89Zr,
/// (126500,DCM,"Pittsburgh compound B C^11^")
THK5317_F18,
/// (C4279748,UMLS,"THK5351 F^18^")
THK5351_F18,
- /// (129502002,SCT,"Thymidine F^18^")
- Thymidine_F18,
/// (126512,DCM,"Trastuzumab ^89^Zr")
Trastuzumab_89Zr,
/// (126749,DCM,"TRC105 ^89^Zr")
TRC105_89Zr,
- /// (724025002,SCT,"Dotatate Ga^68^")
- Dotatate_Ga68,
/// (126739,DCM,"Ublituximab ^89^Zr")
Ublituximab_89Zr,
/// (C4506788,UMLS,"UCB-J C^11^")
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID4031_CommonAnatomicRegion
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:15 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:48 by J. Riesmeier
*
*/
/** Implementation of DCMR Context Group:
* CID 4031 - Common Anatomic Region.
- * (type: extensible, version: 20221224)
+ * (type: extensible, version: 20250709)
*/
class DCMTK_CMR_EXPORT CID4031_CommonAnatomicRegion
: public DSRContextGroup
Bronchus,
/// (80144004,SCT,"Calcaneus")
Calcaneus,
+ /// (113257007,SCT,"Cardiovascular system")
+ CardiovascularSystem,
/// (122494005,SCT,"Cervical spine")
CervicalSpine,
/// (1217257000,SCT,"Cervico-thoracic spine")
CervicoThoracicSpine,
/// (816094009,SCT,"Chest")
Chest,
- /// (416550000,SCT,"Chest and Abdomen")
- ChestAndAbdomen,
/// (416775004,SCT,"Chest, Abdomen and Pelvis")
ChestAbdomenAndPelvis,
+ /// (416550000,SCT,"Chest and Abdomen")
+ ChestAndAbdomen,
/// (51299004,SCT,"Clavicle")
Clavicle,
/// (64688005,SCT,"Coccyx")
LowerLeg,
/// (61685007,SCT,"Lower limb")
LowerLimb,
+ /// (63337009,SCT,"Lower trunk")
+ LowerTrunk,
/// (122496007,SCT,"Lumbar spine")
LumbarSpine,
/// (1217253001,SCT,"Lumbo-sacral spine")
NasalBone,
/// (45048000,SCT,"Neck")
Neck,
- /// (417437006,SCT,"Neck and Chest")
- NeckAndChest,
- /// (416152001,SCT,"Neck, Chest and Abdomen")
- NeckChestAndAbdomen,
/// (416319003,SCT,"Neck, Chest, Abdomen and Pelvis")
NeckChestAbdomenAndPelvis,
+ /// (416152001,SCT,"Neck, Chest and Abdomen")
+ NeckChestAndAbdomen,
+ /// (417437006,SCT,"Neck and Chest")
+ NeckAndChest,
/// (55024004,SCT,"Optic canal")
OpticCanal,
/// (363654007,SCT,"Orbital structure")
SmallIntestine,
/// (421060004,SCT,"Spine")
Spine,
+ /// (737561001,SCT,"Spine and/or cord")
+ SpineAndPerOrCord,
/// (7844006,SCT,"Sternoclavicular joint")
SternoclavicularJoint,
/// (56873002,SCT,"Sternum")
Toe,
/// (44567001,SCT,"Trachea")
Trachea,
+ /// (22943007,SCT,"Trunk")
+ Trunk,
/// (40983000,SCT,"Upper arm")
UpperArm,
/// (53120007,SCT,"Upper limb")
UpperLimb,
+ /// (67734004,SCT,"Upper trunk")
+ UpperTrunk,
/// (431491007,SCT,"Upper urinary tract")
UpperUrinaryTract,
/// (87953007,SCT,"Ureter")
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID42_NumericValueQualifier
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:08 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:42 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID6147_ResponseCriteria
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:16 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:49 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7021_MeasurementReportDocumentTitle
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:17 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:50 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7181_AbstractMultiDimensionalImageModelComponentUnit
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:18 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:51 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7445_DeviceParticipatingRole
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:19 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:52 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7452_OrganizationalRole
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:20 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:52 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7453_PerformingRole
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:21 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:53 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7464_GeneralRegionOfInterestMeasurementModifier
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:22 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:54 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7469_GenericIntensityAndSizeMeasurement
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:23 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:55 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class CID7551_GenericPurposeOfReferenceToImagesAndCoordinatesInMeasurement
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:24 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:56 by J. Riesmeier
*
*/
/*
*
- * Copyright (C) 2015-2022, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class TID1500_MeasurementReport
/** @name specific error conditions for TID 1500 (and included templates) in module dcmsr/cmr
*/
-//@{
+///@{
/// error: there is no measurement report to add content items to
extern DCMTK_CMR_EXPORT const OFConditionConst CMR_EC_NoMeasurementReport;
/// error: the given DICOM object is not a real world value mapping object
extern DCMTK_CMR_EXPORT const OFConditionConst CMR_EC_InvalidRealWorldValueMappingObject;
-//@}
+///@}
/*---------------------*
/*
*
- * Copyright (C) 2016-2017, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2016-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for common error constants used in TID 14xx/15xx
/** @name specific error conditions for TID 1500 (and included templates) in module dcmsr/cmr
*/
-//@{
+///@{
/// error: there is no measurement report to add content items to
extern DCMTK_CMR_EXPORT const OFConditionConst CMR_EC_NoMeasurementReport;
/// error: the given DICOM object is not a real world value mapping object
extern DCMTK_CMR_EXPORT const OFConditionConst CMR_EC_InvalidRealWorldValueMappingObject;
-//@}
+///@}
#endif
/*
*
- * Copyright (C) 2015-2021, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file for class TID1600_ImageLibrary
/** @name specific error conditions for TID 1600 in module dcmsr/cmr
*/
-//@{
+///@{
/// error: there is no image library to add image groups to
extern DCMTK_CMR_EXPORT const OFConditionConst CMR_EC_NoImageLibrary;
/// normal: there are no (common) image library entry descriptors to be moved (to the image group)
extern DCMTK_CMR_EXPORT const OFConditionConst CMR_EC_NoImageLibraryEntryDescriptorsToBeMoved;
-//@}
+///@}
/*---------------------*
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file with DICOM Controlled Terminology Code Definitions (Coding Scheme "DCM", Version "01")
*
- * Generated automatically from DICOM PS 3.16-2024e
- * File created on 2024-11-16 10:17:26 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 11:52:18 by J. Riesmeier
*
*/
* code definitions *
*--------------------*/
-// total number of codes: 4861
-// - retired: 207
+// total number of codes: 5092
+// - retired: 208
// - no name: 27
// - not unique: 17
#define CODE_DCM_Radiofluoroscopy DSRBasicCodedEntry("RF", "DCM", "Radiofluoroscopy")
#define CODE_DCM_RadiographicImaging DSRBasicCodedEntry("RG", "DCM", "Radiographic imaging")
#define CODE_DCM_RadiationTherapyDevice DSRBasicCodedEntry("RT", "DCM", "Radiation Therapy Device")
-#define CODE_DCM_RadiotherapyDose DSRBasicCodedEntry("RTDOSE", "DCM", "Radiotherapy Dose")
-#define CODE_DCM_RadiotherapyImage DSRBasicCodedEntry("RTIMAGE", "DCM", "Radiotherapy Image")
-#define CODE_DCM_RadiotherapyPlan DSRBasicCodedEntry("RTPLAN", "DCM", "Radiotherapy Plan")
-#define CODE_DCM_RadiotherapyTreatmentRecord DSRBasicCodedEntry("RTRECORD", "DCM", "Radiotherapy Treatment Record")
-#define CODE_DCM_RadiotherapyStructureSet DSRBasicCodedEntry("RTSTRUCT", "DCM", "Radiotherapy Structure Set")
+#define CODE_DCM_RTDose DSRBasicCodedEntry("RTDOSE", "DCM", "RT Dose")
+#define CODE_DCM_RTImage DSRBasicCodedEntry("RTIMAGE", "DCM", "RT Image")
+#define CODE_DCM_RTPlan DSRBasicCodedEntry("RTPLAN", "DCM", "RT Plan")
+#define CODE_DCM_RTTreatmentRecord DSRBasicCodedEntry("RTRECORD", "DCM", "RT Treatment Record")
+#define CODE_DCM_RTStructureSet DSRBasicCodedEntry("RTSTRUCT", "DCM", "RT Structure Set")
#define CODE_DCM_RealWorldValueMap DSRBasicCodedEntry("RWV", "DCM", "Real World Value Map")
#define CODE_DCM_Segmentation_SEG DSRBasicCodedEntry("SEG", "DCM", "Segmentation")
#define CODE_DCM_SlideMicroscopy_SM DSRBasicCodedEntry("SM", "DCM", "Slide Microscopy")
#define CODE_DCM_VoltageMeasurementByBasketCatheter DSRBasicCodedEntry("109011", "DCM", "Voltage measurement by basket catheter")
#define CODE_DCM_VoltageMeasurementByMappingCatheter DSRBasicCodedEntry("109012", "DCM", "Voltage measurement by mapping catheter")
#define CODE_DCM_VoltageMeasurement DSRBasicCodedEntry("109013", "DCM", "Voltage measurement")
-#define CODE_DCM_35PercentOfThermalCO DSRBasicCodedEntry("109014", "DCM", "35% of thermal CO")
-#define CODE_DCM_70PercentOfThermalCO DSRBasicCodedEntry("109015", "DCM", "70% of thermal CO")
+#define CODE_DCM_35PercentOfThermalDyeDilutionCO DSRBasicCodedEntry("109014", "DCM", "35% of thermal/dye dilution CO")
+#define CODE_DCM_70PercentOfThermalDyeDilutionCO DSRBasicCodedEntry("109015", "DCM", "70% of thermal/dye dilution CO")
#define CODE_DCM_AWavePeakPressure DSRBasicCodedEntry("109016", "DCM", "A wave peak pressure")
#define CODE_DCM_AWavePressure_average DSRBasicCodedEntry("109017", "DCM", "A wave pressure, average")
#define CODE_DCM_BeatDetected_accepted DSRBasicCodedEntry("109018", "DCM", "Beat detected (accepted)")
#define CODE_DCM_PeakOfThermalCardiacOutputBolus DSRBasicCodedEntry("109028", "DCM", "Peak of thermal cardiac output bolus")
#define CODE_DCM_StartOfExpiration DSRBasicCodedEntry("109029", "DCM", "Start of expiration")
#define CODE_DCM_StartOfInspiration DSRBasicCodedEntry("109030", "DCM", "Start of inspiration")
-#define CODE_DCM_StartOfThermalCardiacOutputBolus DSRBasicCodedEntry("109031", "DCM", "Start of thermal cardiac output bolus")
+#define CODE_DCM_StartOfThermalCO DSRBasicCodedEntry("109031", "DCM", "Start of thermal CO")
#define CODE_DCM_RETIRED_SystolicPressure_average DSRBasicCodedEntry("109032", "DCM", "Systolic pressure, average")
#define CODE_DCM_RETIRED_SystolicPeakPressure DSRBasicCodedEntry("109033", "DCM", "Systolic peak pressure")
#define CODE_DCM_VWavePeakPressure DSRBasicCodedEntry("109034", "DCM", "V wave peak pressure")
#define CODE_DCM_IndividualImpressionRecommendation DSRBasicCodedEntry("111034", "DCM", "Individual Impression/Recommendation")
#define CODE_DCM_LesionDensity DSRBasicCodedEntry("111035", "DCM", "Lesion Density")
#define CODE_DCM_MammographyCADReport DSRBasicCodedEntry("111036", "DCM", "Mammography CAD Report")
-#define CODE_DCM_Margins DSRBasicCodedEntry("111037", "DCM", "Margins")
+#define CODE_DCM_RETIRED_Margins DSRBasicCodedEntry("111037", "DCM", "Margins")
#define CODE_DCM_NumberOfCalcifications DSRBasicCodedEntry("111038", "DCM", "Number of calcifications")
#define CODE_DCM_ObjectType DSRBasicCodedEntry("111039", "DCM", "Object type")
#define CODE_DCM_OriginalSource DSRBasicCodedEntry("111040", "DCM", "Original Source")
#define CODE_DCM_BarrettUniversalII DSRBasicCodedEntry("111865", "DCM", "Barrett Universal II")
#define CODE_DCM_BarrettLensFactor DSRBasicCodedEntry("111866", "DCM", "Barrett Lens Factor")
#define CODE_DCM_BarrettDesignFactor DSRBasicCodedEntry("111867", "DCM", "Barrett Design Factor")
+#define CODE_DCM_Kane DSRBasicCodedEntry("111868", "DCM", "Kane")
+#define CODE_DCM_KaneToric DSRBasicCodedEntry("111869", "DCM", "Kane Toric")
+#define CODE_DCM_KaneKeratoconus DSRBasicCodedEntry("111870", "DCM", "Kane Keratoconus")
+#define CODE_DCM_BarrettKeratoconus DSRBasicCodedEntry("111871", "DCM", "Barrett Keratoconus")
+#define CODE_DCM_BarrettRx DSRBasicCodedEntry("111872", "DCM", "Barrett Rx")
+#define CODE_DCM_EVO DSRBasicCodedEntry("111873", "DCM", "EVO")
+#define CODE_DCM_ShammasNoHistory DSRBasicCodedEntry("111874", "DCM", "Shammas No-History")
+#define CODE_DCM_CamellinCalossi DSRBasicCodedEntry("111875", "DCM", "Camellin-Calossi")
+#define CODE_DCM_HillRBF3dot0 DSRBasicCodedEntry("111876", "DCM", "Hill RBF 3.0")
+#define CODE_DCM_PEARLDGS DSRBasicCodedEntry("111877", "DCM", "PEARL-DGS")
#define CODE_DCM_MaculaCentered DSRBasicCodedEntry("111900", "DCM", "Macula centered")
#define CODE_DCM_DiscCentered DSRBasicCodedEntry("111901", "DCM", "Disc centered")
#define CODE_DCM_LesionCentered DSRBasicCodedEntry("111902", "DCM", "Lesion centered")
#define CODE_DCM_MinimumIntensityProjection DSRBasicCodedEntry("113079", "DCM", "Minimum intensity projection")
#define CODE_DCM_GlutamateAndGlutamine DSRBasicCodedEntry("113080", "DCM", "Glutamate and glutamine")
#define CODE_DCM_CholineCreatineRatio DSRBasicCodedEntry("113081", "DCM", "Choline/Creatine Ratio")
-#define CODE_DCM_NAcetylaspartateCreatineRatio DSRBasicCodedEntry("113082", "DCM", "N-acetylaspartate /Creatine Ratio")
-#define CODE_DCM_NAcetylaspartateCholineRatio DSRBasicCodedEntry("113083", "DCM", "N-acetylaspartate /Choline Ratio")
+#define CODE_DCM_NAcetylaspartateCreatineRatio DSRBasicCodedEntry("113082", "DCM", "N-acetylaspartate/Creatine Ratio")
+#define CODE_DCM_NAcetylaspartateCholineRatio DSRBasicCodedEntry("113083", "DCM", "N-acetylaspartate/Choline Ratio")
#define CODE_DCM_Tmax DSRBasicCodedEntry("113084", "DCM", "Tmax")
#define CODE_DCM_SpatialResampling DSRBasicCodedEntry("113085", "DCM", "Spatial resampling")
#define CODE_DCM_EdgeEnhancement DSRBasicCodedEntry("113086", "DCM", "Edge enhancement")
#define CODE_DCM_PolarToRectangularScanConversion DSRBasicCodedEntry("113093", "DCM", "Polar to Rectangular Scan Conversion")
#define CODE_DCM_CreatineAndCholine DSRBasicCodedEntry("113094", "DCM", "Creatine and Choline")
#define CODE_DCM_LipidAndLactate DSRBasicCodedEntry("113095", "DCM", "Lipid and Lactate")
-#define CODE_DCM_CreatinePlusCholineCitrateRatio DSRBasicCodedEntry("113096", "DCM", "Creatine+Choline/ Citrate Ratio")
+#define CODE_DCM_CreatinePlusCholineCitrateRatio DSRBasicCodedEntry("113096", "DCM", "Creatine+Choline/Citrate Ratio")
#define CODE_DCM_MultiEnergyProportionalWeighting DSRBasicCodedEntry("113097", "DCM", "Multi-energy proportional weighting")
#define CODE_DCM_MagnetizationTransferRatio DSRBasicCodedEntry("113098", "DCM", "Magnetization Transfer Ratio")
#define CODE_DCM_BasicApplicationConfidentialityProfile DSRBasicCodedEntry("113100", "DCM", "Basic Application Confidentiality Profile")
#define CODE_DCM_RetainInstitutionIdentityOption DSRBasicCodedEntry("113112", "DCM", "Retain Institution Identity Option")
#define CODE_DCM_PredecessorContainingGroupOfImagingSubjects DSRBasicCodedEntry("113130", "DCM", "Predecessor containing group of imaging subjects")
#define CODE_DCM_ExtractionOfIndividualSubjectFromGroup DSRBasicCodedEntry("113131", "DCM", "Extraction of individual subject from group")
-#define CODE_DCM_SingleSubjectSelectedFromGroup DSRBasicCodedEntry("113132", "DCM", "Single subject selected from group")
+#define CODE_DCM_SingleSubjectExtractedFromGroup DSRBasicCodedEntry("113132", "DCM", "Single subject extracted from group")
#define CODE_DCM_Trace DSRBasicCodedEntry("113201", "DCM", "Trace")
#define CODE_DCM_MeanDiffusivity DSRBasicCodedEntry("113202", "DCM", "Mean Diffusivity")
#define CODE_DCM_RadialDiffusivity DSRBasicCodedEntry("113203", "DCM", "Radial Diffusivity")
#define CODE_DCM_RadialKurtosis DSRBasicCodedEntry("113207", "DCM", "Radial Kurtosis")
#define CODE_DCM_AxialKurtosis DSRBasicCodedEntry("113208", "DCM", "Axial Kurtosis")
#define CODE_DCM_FractionalKurtosisAnisotropy DSRBasicCodedEntry("113209", "DCM", "Fractional Kurtosis Anisotropy")
-#define CODE_DCM_DeterministicTrackingAlgorithm DSRBasicCodedEntry("113211", "DCM", "Deterministic Tracking Algorithm")
-#define CODE_DCM_ProbabilisticTrackingAlgorithm DSRBasicCodedEntry("113212", "DCM", "Probabilistic Tracking Algorithm")
-#define CODE_DCM_GlobalTrackingAlgorithm DSRBasicCodedEntry("113213", "DCM", "Global Tracking Algorithm")
+#define CODE_DCM_Deterministic DSRBasicCodedEntry("113211", "DCM", "Deterministic")
+#define CODE_DCM_Probabilistic DSRBasicCodedEntry("113212", "DCM", "Probabilistic")
+#define CODE_DCM_Global DSRBasicCodedEntry("113213", "DCM", "Global")
#define CODE_DCM_FACT DSRBasicCodedEntry("113214", "DCM", "FACT")
#define CODE_DCM_Streamline DSRBasicCodedEntry("113215", "DCM", "Streamline")
#define CODE_DCM_TEND DSRBasicCodedEntry("113216", "DCM", "TEND")
-#define CODE_DCM_BootstrapTrackingAlgorithm DSRBasicCodedEntry("113217", "DCM", "Bootstrap Tracking Algorithm")
+#define CODE_DCM_Bootstrap DSRBasicCodedEntry("113217", "DCM", "Bootstrap")
#define CODE_DCM_Euler DSRBasicCodedEntry("113218", "DCM", "Euler")
#define CODE_DCM_RungeKutta DSRBasicCodedEntry("113219", "DCM", "Runge-Kutta")
#define CODE_DCM_HARDI DSRBasicCodedEntry("113221", "DCM", "HARDI")
#define CODE_DCM_DSI DSRBasicCodedEntry("113224", "DCM", "DSI")
#define CODE_DCM_LSDI DSRBasicCodedEntry("113225", "DCM", "LSDI")
#define CODE_DCM_SingleShotEPI DSRBasicCodedEntry("113226", "DCM", "Single Shot EPI")
-#define CODE_DCM_MultiShotEPI DSRBasicCodedEntry("113227", "DCM", "Multi Shot EPI")
+#define CODE_DCM_MultipleShotEPI DSRBasicCodedEntry("113227", "DCM", "Multiple Shot EPI")
#define CODE_DCM_ParallelImaging DSRBasicCodedEntry("113228", "DCM", "Parallel Imaging")
#define CODE_DCM_SingleTensor DSRBasicCodedEntry("113231", "DCM", "Single Tensor")
#define CODE_DCM_MultiTensor DSRBasicCodedEntry("113232", "DCM", "Multi Tensor")
#define CODE_DCM_ICRPPublication53 DSRBasicCodedEntry("113521", "DCM", "ICRP Publication 53")
#define CODE_DCM_ICRPPublication80 DSRBasicCodedEntry("113522", "DCM", "ICRP Publication 80")
#define CODE_DCM_ICRPPublication106 DSRBasicCodedEntry("113523", "DCM", "ICRP Publication 106")
+#define CODE_DCM_ICRPPublication128 DSRBasicCodedEntry("113524", "DCM", "ICRP Publication 128")
+#define CODE_DCM_RADAR2017 DSRBasicCodedEntry("113525", "DCM", "RADAR 2017")
#define CODE_DCM_MIRDOSE DSRBasicCodedEntry("113526", "DCM", "MIRDOSE")
#define CODE_DCM_OLINDAEXM DSRBasicCodedEntry("113527", "DCM", "OLINDA-EXM")
#define CODE_DCM_PackageInsert DSRBasicCodedEntry("113528", "DCM", "Package Insert")
#define CODE_DCM_ActivityMeasurementDevice DSRBasicCodedEntry("113540", "DCM", "Activity Measurement Device")
#define CODE_DCM_DoseCalibrator DSRBasicCodedEntry("113541", "DCM", "Dose Calibrator")
#define CODE_DCM_InfusionSystem DSRBasicCodedEntry("113542", "DCM", "Infusion System")
-#define CODE_DCM_Generator DSRBasicCodedEntry("113543", "DCM", "Generator")
+#define CODE_DCM_RadioisotopeGenerator DSRBasicCodedEntry("113543", "DCM", "Radioisotope Generator")
#define CODE_DCM_FastingDuration DSRBasicCodedEntry("113550", "DCM", "Fasting Duration")
#define CODE_DCM_HydrationVolume DSRBasicCodedEntry("113551", "DCM", "Hydration Volume")
#define CODE_DCM_RecentPhysicalActivity DSRBasicCodedEntry("113552", "DCM", "Recent Physical Activity")
#define CODE_DCM_ACRAccreditationPhantom_PET DSRBasicCodedEntry("113687", "DCM", "ACR Accreditation Phantom - PET")
#define CODE_DCM_ACRAccreditationPhantom_ECTPET DSRBasicCodedEntry("113688", "DCM", "ACR Accreditation Phantom - ECT/PET")
#define CODE_DCM_ACRAccreditationPhantom_PETFaceplate DSRBasicCodedEntry("113689", "DCM", "ACR Accreditation Phantom - PET Faceplate")
-#define CODE_DCM_IECHeadDosimetryPhantom DSRBasicCodedEntry("113690", "DCM", "IEC Head Dosimetry Phantom")
-#define CODE_DCM_IECBodyDosimetryPhantom DSRBasicCodedEntry("113691", "DCM", "IEC Body Dosimetry Phantom")
+#define CODE_DCM_IEC160mmHeadCTDosimetryPhantom DSRBasicCodedEntry("113690", "DCM", "IEC 160mm Head CT Dosimetry Phantom")
+#define CODE_DCM_IEC320mmBodyCTDosimetryPhantom DSRBasicCodedEntry("113691", "DCM", "IEC 320mm Body CT Dosimetry Phantom")
#define CODE_DCM_NEMAXR212000Phantom DSRBasicCodedEntry("113692", "DCM", "NEMA XR21-2000 Phantom")
#define CODE_DCM_XRayRadiationDoseReport DSRBasicCodedEntry("113701", "DCM", "X-Ray Radiation Dose Report")
#define CODE_DCM_AccumulatedXRayDoseData DSRBasicCodedEntry("113702", "DCM", "Accumulated X-Ray Dose Data")
#define CODE_DCM_PerformedProcedureStepSOPInstanceUID DSRBasicCodedEntry("121126", "DCM", "Performed Procedure Step SOP Instance UID")
#define CODE_DCM_PerformedProcedureStepSOPClassUID DSRBasicCodedEntry("121127", "DCM", "Performed Procedure Step SOP Class UID")
#define CODE_DCM_ProcedureActionDuration DSRBasicCodedEntry("121128", "DCM", "Procedure Action Duration")
-#define CODE_DCM_StartProcedureActionItem DSRBasicCodedEntry("121130", "DCM", "Start Procedure Action Item")
-#define CODE_DCM_EndProcedureActionItem DSRBasicCodedEntry("121131", "DCM", "End Procedure Action Item")
-#define CODE_DCM_SuspendProcedureActionItem DSRBasicCodedEntry("121132", "DCM", "Suspend Procedure Action Item")
-#define CODE_DCM_ResumeProcedureActionItem DSRBasicCodedEntry("121133", "DCM", "Resume Procedure Action Item")
+#define CODE_DCM_StartProcedureAction DSRBasicCodedEntry("121130", "DCM", "Start Procedure Action")
+#define CODE_DCM_EndProcedureAction DSRBasicCodedEntry("121131", "DCM", "End Procedure Action")
+#define CODE_DCM_SuspendProcedureAction DSRBasicCodedEntry("121132", "DCM", "Suspend Procedure Action")
+#define CODE_DCM_ResumeProcedureAction DSRBasicCodedEntry("121133", "DCM", "Resume Procedure Action")
#define CODE_DCM_ObservationDateTimeQualifier DSRBasicCodedEntry("121135", "DCM", "Observation DateTime Qualifier")
#define CODE_DCM_DateTimeUnsynchronized DSRBasicCodedEntry("121136", "DCM", "DateTime Unsynchronized")
#define CODE_DCM_DateTimeEstimated DSRBasicCodedEntry("121137", "DCM", "DateTime Estimated")
#define CODE_DCM_OxygenAdministrationRate DSRBasicCodedEntry("121160", "DCM", "Oxygen Administration Rate")
#define CODE_DCM_BeginOxygenAdministration DSRBasicCodedEntry("121161", "DCM", "Begin Oxygen Administration")
#define CODE_DCM_EndOxygenAdministration DSRBasicCodedEntry("121162", "DCM", "End oxygen administration")
-#define CODE_DCM_ByVentilator DSRBasicCodedEntry("121163", "DCM", "By ventilator")
+#define CODE_DCM_OxygenAdministrationByVentilator DSRBasicCodedEntry("121163", "DCM", "Oxygen Administration by ventilator")
#define CODE_DCM_PatientAssessmentPerformed DSRBasicCodedEntry("121165", "DCM", "Patient Assessment Performed")
#define CODE_DCM_BeginPacing DSRBasicCodedEntry("121166", "DCM", "Begin Pacing")
#define CODE_DCM_EndPacing DSRBasicCodedEntry("121167", "DCM", "End Pacing")
#define CODE_DCM_AddendedReport DSRBasicCodedEntry("121361", "DCM", "Addended report")
#define CODE_DCM_PreliminaryReport DSRBasicCodedEntry("121362", "DCM", "Preliminary report")
#define CODE_DCM_PartialReport DSRBasicCodedEntry("121363", "DCM", "Partial report")
+#define CODE_DCM_ComposedFromDeformableRegistration DSRBasicCodedEntry("121367", "DCM", "Composed from deformable registration")
+#define CODE_DCM_ComposedFromImageSeriesOtherThanPlanningImageSeries DSRBasicCodedEntry("121368", "DCM", "Composed from image series other than planning image series")
+#define CODE_DCM_ComposedFromSetupPerturbation DSRBasicCodedEntry("121369", "DCM", "Composed from setup perturbation")
#define CODE_DCM_ComposedFromPriorDoses DSRBasicCodedEntry("121370", "DCM", "Composed from prior doses")
#define CODE_DCM_ComposedFromPriorDosesAndCurrentPlan DSRBasicCodedEntry("121371", "DCM", "Composed from prior doses and current plan")
#define CODE_DCM_SourceDoseForComposingCurrentDose DSRBasicCodedEntry("121372", "DCM", "Source dose for composing current dose")
#define CODE_DCM_NumberOfFractionsCompleted DSRBasicCodedEntry("121387", "DCM", "Number of Fractions Completed")
#define CODE_DCM_CheckedInStatus DSRBasicCodedEntry("121388", "DCM", "Checked-In Status")
#define CODE_DCM_ReferencedBeamNumber DSRBasicCodedEntry("121389", "DCM", "Referenced Beam Number")
+#define CODE_DCM_ClinicalFractionNumber DSRBasicCodedEntry("121390", "DCM", "Clinical Fraction Number")
#define CODE_DCM_Derivation DSRBasicCodedEntry("121401", "DCM", "Derivation")
#define CODE_DCM_Normality DSRBasicCodedEntry("121402", "DCM", "Normality")
#define CODE_DCM_LevelOfSignificance DSRBasicCodedEntry("121403", "DCM", "Level of Significance")
#define CODE_DCM_RTTreatmentQAByRTPlanDoseCheck DSRBasicCodedEntry("121731", "DCM", "RT Treatment QA by RT Plan Dose Check")
#define CODE_DCM_RTTreatmentQAByRTPlanDifferenceCheck DSRBasicCodedEntry("121732", "DCM", "RT Treatment QA by RT Plan Difference Check")
#define CODE_DCM_RTTreatmentQAByRTIonPlanDoseCheck DSRBasicCodedEntry("121733", "DCM", "RT Treatment QA by RT Ion Plan Dose Check")
-#define CODE_DCM_RTTreatmentQAWithRTIonPlanDifferenceCheck DSRBasicCodedEntry("121734", "DCM", "RT Treatment QA with RT Ion Plan Difference Check")
+#define CODE_DCM_RTTreatmentQAByRTIonPlanDifferenceCheck DSRBasicCodedEntry("121734", "DCM", "RT Treatment QA by RT Ion Plan Difference Check")
#define CODE_DCM_RTBrachyTreatment DSRBasicCodedEntry("121735", "DCM", "RT Brachy Treatment")
#define CODE_DCM_RTImageGuidedPatientPositioningAndTreatmentDelivery DSRBasicCodedEntry("121736", "DCM", "RT Image-Guided Patient Positioning and Treatment Delivery")
#define CODE_DCM_RTPatientPositionAcquisition_MR DSRBasicCodedEntry("121737", "DCM", "RT Patient Position Acquisition, MR")
#define CODE_DCM_Probability DSRBasicCodedEntry("122157", "DCM", "Probability")
#define CODE_DCM_ECGGlobalMeasurements DSRBasicCodedEntry("122158", "DCM", "ECG Global Measurements")
#define CODE_DCM_ECGLeadMeasurements DSRBasicCodedEntry("122159", "DCM", "ECG Lead Measurements")
-#define CODE_DCM_DerivedArea_NonValve DSRBasicCodedEntry("122160", "DCM", "Derived Area, Non-Valve")
+#define CODE_DCM_DerivedNonValveArea DSRBasicCodedEntry("122160", "DCM", "Derived Non-Valve Area")
#define CODE_DCM_PulmonaryFlow DSRBasicCodedEntry("122161", "DCM", "Pulmonary Flow")
#define CODE_DCM_SystemicFlow DSRBasicCodedEntry("122162", "DCM", "Systemic Flow")
#define CODE_DCM_DischargeDateTime DSRBasicCodedEntry("122163", "DCM", "Discharge DateTime")
#define CODE_DCM_TerritoryRegionSeverity DSRBasicCodedEntry("122459", "DCM", "Territory Region Severity")
#define CODE_DCM_OppositeRegionSeverity DSRBasicCodedEntry("122461", "DCM", "Opposite Region Severity")
#define CODE_DCM_LADRegionInRAOProjection DSRBasicCodedEntry("122464", "DCM", "LAD Region in RAO Projection")
-#define CODE_DCM_RCARegionInROAProjection DSRBasicCodedEntry("122465", "DCM", "RCA Region in ROA Projection")
+#define CODE_DCM_RCARegionInRAOProjection DSRBasicCodedEntry("122465", "DCM", "RCA Region in RAO Projection")
#define CODE_DCM_SingleLADRegionInRAOProjection DSRBasicCodedEntry("122466", "DCM", "Single LAD Region in RAO Projection")
#define CODE_DCM_SingleRCARegionInRAOProjection DSRBasicCodedEntry("122467", "DCM", "Single RCA Region in RAO Projection")
#define CODE_DCM_MultipleLADRegionInRAOProjection DSRBasicCodedEntry("122468", "DCM", "Multiple LAD Region in RAO Projection")
#define CODE_DCM_STDepression_Downsloping DSRBasicCodedEntry("122759", "DCM", "ST Depression - Downsloping")
#define CODE_DCM_StressTestScore DSRBasicCodedEntry("122760", "DCM", "Stress test score")
#define CODE_DCM_NumberOfDiseasedVesselTerritories DSRBasicCodedEntry("122762", "DCM", "Number of diseased vessel territories")
-#define CODE_DCM_WeightExceedsEquipmentLimit DSRBasicCodedEntry("122764", "DCM", "Weight exceeds equipment limit")
+#define CODE_DCM_PatientWeightExceedsEquipmentLimit DSRBasicCodedEntry("122764", "DCM", "Patient weight exceeds equipment limit")
#define CODE_DCM_DifferenceInEjectionFraction DSRBasicCodedEntry("122768", "DCM", "Difference in Ejection Fraction")
#define CODE_DCM_DifferenceInEDLVVolume DSRBasicCodedEntry("122769", "DCM", "Difference in ED LV Volume")
#define CODE_DCM_RatioOfAchievedToPredictedMaximalOxygenConsumption DSRBasicCodedEntry("122770", "DCM", "Ratio of achieved to predicted maximal oxygen consumption")
#define CODE_DCM_AcquisitionProtocol DSRBasicCodedEntry("125203", "DCM", "Acquisition Protocol")
#define CODE_DCM_AreaLengthBiplane DSRBasicCodedEntry("125204", "DCM", "Area-length biplane")
#define CODE_DCM_AreaLengthSinglePlane DSRBasicCodedEntry("125205", "DCM", "Area-Length Single Plane")
-#define CODE_DCM_Cube DSRBasicCodedEntry("125206", "DCM", "Cube")
+#define CODE_DCM_CubeMethod DSRBasicCodedEntry("125206", "DCM", "Cube Method")
#define CODE_DCM_MethodOfDisks_Biplane DSRBasicCodedEntry("125207", "DCM", "Method of Disks, Biplane")
#define CODE_DCM_MethodOfDisks_SinglePlane DSRBasicCodedEntry("125208", "DCM", "Method of Disks, Single Plane")
#define CODE_DCM_Teichholz DSRBasicCodedEntry("125209", "DCM", "Teichholz")
#define CODE_DCM_Glycolysis DSRBasicCodedEntry("126034", "DCM", "Glycolysis")
#define CODE_DCM_TotalLesionProliferation DSRBasicCodedEntry("126035", "DCM", "Total Lesion Proliferation")
#define CODE_DCM_ProliferativeActivity DSRBasicCodedEntry("126036", "DCM", "Proliferative Activity")
-#define CODE_DCM_StandardizedAddedMetabolicActivity_SAM DSRBasicCodedEntry("126037", "DCM", "Standardized Added Metabolic Activity (SAM)")
-#define CODE_DCM_StandardizedAddedMetabolicActivity_SAM_Background DSRBasicCodedEntry("126038", "DCM", "Standardized Added Metabolic Activity (SAM) Background")
+#define CODE_DCM_StandardizedAddedMetabolicActivity DSRBasicCodedEntry("126037", "DCM", "Standardized Added Metabolic Activity")
+#define CODE_DCM_StandardizedAddedMetabolicActivityBackground DSRBasicCodedEntry("126038", "DCM", "Standardized Added Metabolic Activity Background")
#define CODE_DCM_LesionToBackgroundSUVRatio DSRBasicCodedEntry("126039", "DCM", "Lesion to Background SUV Ratio")
#define CODE_DCM_BackgroundForLesionToBackgroundSUVRatio DSRBasicCodedEntry("126040", "DCM", "Background for Lesion to Background SUV Ratio")
#define CODE_DCM_FractalDimension DSRBasicCodedEntry("126050", "DCM", "Fractal Dimension")
#define CODE_DCM_PerfusionAnalysisByIVIodinatedContrastCTTechnique DSRBasicCodedEntry("126301", "DCM", "Perfusion analysis by IV Iodinated Contrast CT technique")
#define CODE_DCM_PerfusionAnalysisByArterialSpinLabelingMRTechnique DSRBasicCodedEntry("126302", "DCM", "Perfusion analysis by Arterial Spin Labeling MR technique")
#define CODE_DCM_PerfusionAnalysisBySusceptibilityMRTechnique DSRBasicCodedEntry("126303", "DCM", "Perfusion analysis by Susceptibility MR technique")
-#define CODE_DCM_LeastMeanSquare_LMS_deconvolution DSRBasicCodedEntry("126310", "DCM", "Least Mean Square (LMS) deconvolution")
-#define CODE_DCM_SingularValueDecomposition_SVD_deconvolution DSRBasicCodedEntry("126311", "DCM", "Singular Value Decomposition (SVD) deconvolution")
+#define CODE_DCM_LeastMeanSquareDeconvolution DSRBasicCodedEntry("126310", "DCM", "Least Mean Square deconvolution")
+#define CODE_DCM_SingularValueDecompositionDeconvolution DSRBasicCodedEntry("126311", "DCM", "Singular Value Decomposition deconvolution")
#define CODE_DCM_Ktrans DSRBasicCodedEntry("126312", "DCM", "Ktrans")
#define CODE_DCM_Kep DSRBasicCodedEntry("126313", "DCM", "kep")
#define CODE_DCM_Ve DSRBasicCodedEntry("126314", "DCM", "ve")
#define CODE_DCM_IAUC90 DSRBasicCodedEntry("126322", "DCM", "IAUC90")
#define CODE_DCM_IAUC180 DSRBasicCodedEntry("126323", "DCM", "IAUC180")
#define CODE_DCM_IAUCBN DSRBasicCodedEntry("126324", "DCM", "IAUCBN")
-#define CODE_DCM_IAUCBN60 DSRBasicCodedEntry("126325", "DCM", "IAUCBN60")
-#define CODE_DCM_IAUCBN90 DSRBasicCodedEntry("126326", "DCM", "IAUCBN90")
-#define CODE_DCM_AUCBN180 DSRBasicCodedEntry("126327", "DCM", "AUCBN180")
+#define CODE_DCM_IAUC60BN DSRBasicCodedEntry("126325", "DCM", "IAUC60BN")
+#define CODE_DCM_IAUC90BN DSRBasicCodedEntry("126326", "DCM", "IAUC90BN")
+#define CODE_DCM_IAUC180BN DSRBasicCodedEntry("126327", "DCM", "IAUC180BN")
#define CODE_DCM_Tau_m DSRBasicCodedEntry("126330", "DCM", "tau_m")
#define CODE_DCM_Vp DSRBasicCodedEntry("126331", "DCM", "vp")
#define CODE_DCM_StandardToftsModel DSRBasicCodedEntry("126340", "DCM", "Standard Tofts Model")
#define CODE_DCM_ExtendedToftsModel DSRBasicCodedEntry("126341", "DCM", "Extended Tofts Model")
#define CODE_DCM_ModelFreeConcentrationTimeQuantitification DSRBasicCodedEntry("126342", "DCM", "Model-free concentration-time quantitification")
-#define CODE_DCM_FirstPassLeakageProfile_FPLP_Model DSRBasicCodedEntry("126343", "DCM", "First Pass Leakage Profile (FPLP) Model")
-#define CODE_DCM_ShutterSpeedModel_SSM DSRBasicCodedEntry("126344", "DCM", "Shutter-Speed Model (SSM)")
-#define CODE_DCM_GammaCapillaryTransitTime_GCCT_Model DSRBasicCodedEntry("126345", "DCM", "Gamma Capillary Transit Time (GCCT) Model")
-#define CODE_DCM_AdiabaticTissueHomogeneity_ATH_Model DSRBasicCodedEntry("126346", "DCM", "Adiabatic Tissue Homogeneity (ATH) Model")
-#define CODE_DCM_TwoCompartmentExchange_2CX_Model DSRBasicCodedEntry("126347", "DCM", "Two Compartment Exchange (2CX) Model")
+#define CODE_DCM_FirstPassLeakageProfileModel DSRBasicCodedEntry("126343", "DCM", "First Pass Leakage Profile Model")
+#define CODE_DCM_ShutterSpeedModel DSRBasicCodedEntry("126344", "DCM", "Shutter-Speed Model")
+#define CODE_DCM_GammaCapillaryTransitTimeModel DSRBasicCodedEntry("126345", "DCM", "Gamma Capillary Transit Time Model")
+#define CODE_DCM_AdiabaticTissueHomogeneityModel DSRBasicCodedEntry("126346", "DCM", "Adiabatic Tissue Homogeneity Model")
+#define CODE_DCM_TwoCompartmentExchangeModel DSRBasicCodedEntry("126347", "DCM", "Two Compartment Exchange Model")
#define CODE_DCM_T1ByMultipleFlipAngles DSRBasicCodedEntry("126350", "DCM", "T1 by Multiple Flip Angles")
#define CODE_DCM_T1ByInversionRecovery DSRBasicCodedEntry("126351", "DCM", "T1 by Inversion Recovery")
#define CODE_DCM_T1ByFixedValue DSRBasicCodedEntry("126352", "DCM", "T1 by Fixed Value")
#define CODE_DCM_T807_F18 DSRBasicCodedEntry("126502", "DCM", "T807 F^18^")
#define CODE_DCM_Flubatine_F18 DSRBasicCodedEntry("126503", "DCM", "Flubatine F^18^")
#define CODE_DCM_Lutetium177NAcetylaspartylglutamate DSRBasicCodedEntry("126509", "DCM", "Lutetium^177^ n-acetylaspartylglutamate")
-#define CODE_DCM_MonoclonalAntibody_mAb_64Cu DSRBasicCodedEntry("126510", "DCM", "Monoclonal Antibody (mAb) ^64^Cu")
-#define CODE_DCM_MonoclonalAntibody_mAb_89Zr DSRBasicCodedEntry("126511", "DCM", "Monoclonal Antibody (mAb) ^89^Zr")
+#define CODE_DCM_MonoclonalAntibody_64Cu DSRBasicCodedEntry("126510", "DCM", "Monoclonal Antibody ^64^Cu")
+#define CODE_DCM_MonoclonalAntibody_89Zr DSRBasicCodedEntry("126511", "DCM", "Monoclonal Antibody ^89^Zr")
#define CODE_DCM_Trastuzumab_89Zr DSRBasicCodedEntry("126512", "DCM", "Trastuzumab ^89^Zr")
#define CODE_DCM_Cetuximab_89Zr DSRBasicCodedEntry("126513", "DCM", "Cetuximab ^89^Zr")
#define CODE_DCM_J591_89Zr DSRBasicCodedEntry("126514", "DCM", "J591 ^89^Zr")
#define CODE_DCM_R1507_89Zr DSRBasicCodedEntry("126518", "DCM", "R1507 ^89^Zr")
#define CODE_DCM_E4G10_89Zr DSRBasicCodedEntry("126519", "DCM", "E4G10 ^89^Zr")
#define CODE_DCM_DfCD45_89Zr DSRBasicCodedEntry("126520", "DCM", "Df-CD45 ^89^Zr")
+#define CODE_DCM_Glucose_C11 DSRBasicCodedEntry("126521", "DCM", "Glucose C^11^")
#define CODE_DCM_44Scandium DSRBasicCodedEntry("126600", "DCM", "^44^Scandium")
#define CODE_DCM_51Manganese DSRBasicCodedEntry("126601", "DCM", "^51^Manganese")
#define CODE_DCM_70Arsenic DSRBasicCodedEntry("126602", "DCM", "^70^Arsenic")
#define CODE_DCM_HeadAndNeckImagingSpecialty DSRBasicCodedEntry("128008", "DCM", "Head and Neck Imaging Specialty")
#define CODE_DCM_MusculoskeletalImagingSpecialty DSRBasicCodedEntry("128009", "DCM", "Musculoskeletal Imaging Specialty")
#define CODE_DCM_NeurologySpecialty DSRBasicCodedEntry("128010", "DCM", "Neurology Specialty")
-#define CODE_DCM_NeuroradiologicImagingSpecialty DSRBasicCodedEntry("128011", "DCM", "Neuroradiologic Imaging Specialty")
+#define CODE_DCM_NeuroradiologyImagingSpecialty DSRBasicCodedEntry("128011", "DCM", "Neuroradiology Imaging Specialty")
#define CODE_DCM_OBGynImagingSpecialty DSRBasicCodedEntry("128012", "DCM", "OB/Gyn Imaging Specialty")
#define CODE_DCM_OncologicImagingSpecialty DSRBasicCodedEntry("128013", "DCM", "Oncologic Imaging Specialty")
#define CODE_DCM_OncologySpecialty DSRBasicCodedEntry("128014", "DCM", "Oncology Specialty")
#define CODE_DCM_SkinDoseMap DSRBasicCodedEntry("128485", "DCM", "Skin Dose Map")
#define CODE_DCM_3DDoseMap DSRBasicCodedEntry("128487", "DCM", "3D Dose Map")
#define CODE_DCM_DoseGradient DSRBasicCodedEntry("128488", "DCM", "Dose Gradient")
-#define CODE_DCM_PhysicalSupport DSRBasicCodedEntry("128492", "DCM", "Physical Support")
+#define CODE_DCM_PatientSupport DSRBasicCodedEntry("128492", "DCM", "Patient Support")
#define CODE_DCM_PatientSegmentedModel DSRBasicCodedEntry("128494", "DCM", "Patient Segmented Model")
#define CODE_DCM_DosePointCloud DSRBasicCodedEntry("128496", "DCM", "Dose Point Cloud")
#define CODE_DCM_MeasuredRadiationDose DSRBasicCodedEntry("128497", "DCM", "Measured Radiation Dose")
#define CODE_DCM_FixationOrPositioningDevice DSRBasicCodedEntry("130044", "DCM", "Fixation or Positioning Device")
#define CODE_DCM_BrachytherapyDevice DSRBasicCodedEntry("130045", "DCM", "Brachytherapy Device")
#define CODE_DCM_NonSpecificVolume DSRBasicCodedEntry("130046", "DCM", "Non-specific Volume")
-#define CODE_DCM_ExternalBodyStructure DSRBasicCodedEntry("130047", "DCM", "External Body Structure")
+#define CODE_DCM_ExternalBodyModel DSRBasicCodedEntry("130047", "DCM", "External Body Model")
#define CODE_DCM_UnclassifiedVolume DSRBasicCodedEntry("130048", "DCM", "Unclassified Volume")
#define CODE_DCM_CTVNodal DSRBasicCodedEntry("130049", "DCM", "CTV Nodal")
#define CODE_DCM_CTVPrimary DSRBasicCodedEntry("130050", "DCM", "CTV Primary")
#define CODE_DCM_SkinOfUpperEyelidMargin DSRBasicCodedEntry("130322", "DCM", "Skin of upper eyelid margin")
#define CODE_DCM_SkinOfMidBack DSRBasicCodedEntry("130323", "DCM", "Skin of mid back")
#define CODE_DCM_FunctionalConditionPresentDuringAcquisition DSRBasicCodedEntry("130324", "DCM", "Functional condition present during acquisition")
+#define CODE_DCM_OrthognathicFunctionalCondition DSRBasicCodedEntry("130325", "DCM", "Orthognathic Functional Condition")
#define CODE_DCM_JawPair DSRBasicCodedEntry("130330", "DCM", "Jaw Pair")
#define CODE_DCM_LeafPairs DSRBasicCodedEntry("130331", "DCM", "Leaf Pairs")
#define CODE_DCM_VariableCircularCollimator DSRBasicCodedEntry("130332", "DCM", "Variable Circular Collimator")
#define CODE_DCM_PatientDecisionToTerminateTreatment DSRBasicCodedEntry("130451", "DCM", "Patient decision to terminate treatment")
#define CODE_DCM_PhysicianDecisionToTerminateTreatment DSRBasicCodedEntry("130452", "DCM", "Physician decision to terminate treatment")
#define CODE_DCM_TreatmentTerminated DSRBasicCodedEntry("130453", "DCM", "Treatment Terminated")
-#define CODE_DCM_ResolvedByOverridingInterlock DSRBasicCodedEntry("130454", "DCM", "Resolved by overriding Interlock")
-#define CODE_DCM_ResolvedByRepositioningPatient DSRBasicCodedEntry("130455", "DCM", "Resolved by repositioning Patient")
+#define CODE_DCM_InterlockOverridden DSRBasicCodedEntry("130454", "DCM", "Interlock Overridden")
+#define CODE_DCM_PatientRepositioned DSRBasicCodedEntry("130455", "DCM", "Patient Repositioned")
#define CODE_DCM_BolusPresent DSRBasicCodedEntry("130456", "DCM", "Bolus Present")
#define CODE_DCM_ConePresent DSRBasicCodedEntry("130457", "DCM", "Cone Present")
#define CODE_DCM_BlockPresent DSRBasicCodedEntry("130458", "DCM", "Block Present")
#define CODE_DCM_PatientSupportOrigin DSRBasicCodedEntry("130538", "DCM", "Patient Support Origin")
#define CODE_DCM_IsocenterOrigin DSRBasicCodedEntry("130539", "DCM", "Isocenter Origin")
#define CODE_DCM_PatientCoordinateSystemOrigin DSRBasicCodedEntry("130540", "DCM", "Patient Coordinate System Origin")
-#define CODE_DCM_10cmDosimetryPhantom DSRBasicCodedEntry("130541", "DCM", "10 cm Dosimetry Phantom")
+#define CODE_DCM_100mmPediatricHeadCTDosimetryPhantom DSRBasicCodedEntry("130541", "DCM", "100 mm Pediatric Head CT Dosimetry Phantom")
#define CODE_DCM_MagneticFieldStrength DSRBasicCodedEntry("130542", "DCM", "Magnetic field strength")
#define CODE_DCM_EndorectalCoilUsed DSRBasicCodedEntry("130543", "DCM", "Endorectal coil used")
#define CODE_DCM_EndorectalCoilType DSRBasicCodedEntry("130544", "DCM", "Endorectal coil type")
#define CODE_DCM_O9 DSRBasicCodedEntry("130716", "DCM", "O9")
#define CODE_DCM_O10 DSRBasicCodedEntry("130717", "DCM", "O10")
#define CODE_DCM_CoronaryArteryDiseaseAssessment DSRBasicCodedEntry("130720", "DCM", "Coronary Artery Disease Assessment")
-#define CODE_DCM_OronaryArteryDiseaseAssessmentModifier DSRBasicCodedEntry("130721", "DCM", "oronary Artery Disease Assessment Modifier")
+#define CODE_DCM_CoronaryArteryDiseaseAssessmentModifier DSRBasicCodedEntry("130721", "DCM", "Coronary Artery Disease Assessment Modifier")
#define CODE_DCM_CoronaryArteryDiseaseStenosisAssessmentModifier DSRBasicCodedEntry("130722", "DCM", "Coronary Artery Disease Stenosis Assessment Modifier")
#define CODE_DCM_0_DocumentedAbsenceOfCAD DSRBasicCodedEntry("130723", "DCM", "0 - Documented absence of CAD")
#define CODE_DCM_1_MinimalNonObstructiveCAD DSRBasicCodedEntry("130724", "DCM", "1 - Minimal non-obstructive CAD")
#define CODE_DCM_TricuspidValveAnnulusDiameter DSRBasicCodedEntry("131061", "DCM", "Tricuspid valve annulus diameter")
#define CODE_DCM_IVCSWavePeakVelocity DSRBasicCodedEntry("131062", "DCM", "IVC S-wave peak velocity")
#define CODE_DCM_IVCAWavePeakVelocity DSRBasicCodedEntry("131063", "DCM", "IVC a-wave peak velocity")
+#define CODE_DCM_PreProceduralStructuralHeartMeasurementReport DSRBasicCodedEntry("131090", "DCM", "Pre-procedural Structural Heart Measurement Report")
+#define CODE_DCM_IntraProceduralStructuralHeartMeasurementReport DSRBasicCodedEntry("131091", "DCM", "Intra-procedural Structural Heart Measurement Report")
+#define CODE_DCM_PostProceduralStructuralHeartMeasurementReport DSRBasicCodedEntry("131092", "DCM", "Post-procedural Structural Heart Measurement Report")
+#define CODE_DCM_MidEsophageal0DegreeTEE DSRBasicCodedEntry("131100", "DCM", "Mid-esophageal 0 degree TEE")
+#define CODE_DCM_MidEsophageal45DegreeTEE DSRBasicCodedEntry("131101", "DCM", "Mid-esophageal 45 degree TEE")
+#define CODE_DCM_MidEsophageal60DegreeTEE DSRBasicCodedEntry("131102", "DCM", "Mid-esophageal 60 degree TEE")
+#define CODE_DCM_MidEsophageal90DegreeTEE DSRBasicCodedEntry("131103", "DCM", "Mid-esophageal 90 degree TEE")
+#define CODE_DCM_MidEsophageal135DegreeTEE DSRBasicCodedEntry("131104", "DCM", "Mid-esophageal 135 degree TEE")
+#define CODE_DCM_BallAndDiskTypeLeftAtrialAppendageClosureDevice DSRBasicCodedEntry("131110", "DCM", "Ball and disk type left atrial appendage closure device")
+#define CODE_DCM_BallTypeLeftAtrialAppendageClosureDevice DSRBasicCodedEntry("131111", "DCM", "Ball type left atrial appendage closure device")
+#define CODE_DCM_LeftAtrialAppendageClosureDevice DSRBasicCodedEntry("131112", "DCM", "Left atrial appendage closure device")
+#define CODE_DCM_OstiumOfLeftAuricularAppendage DSRBasicCodedEntry("131120", "DCM", "Ostium of Left Auricular Appendage")
+#define CODE_DCM_TransseptalPunctureHeight DSRBasicCodedEntry("131130", "DCM", "Transseptal puncture height")
+#define CODE_DCM_AortaSinotubularJunctionArea DSRBasicCodedEntry("131140", "DCM", "Aorta sinotubular junction area")
+#define CODE_DCM_AorticAnnulusCalcificationSeverity DSRBasicCodedEntry("131142", "DCM", "Aortic annulus calcification severity")
+#define CODE_DCM_AorticAnnulusMaxDiameter DSRBasicCodedEntry("131143", "DCM", "Aortic annulus max diameter")
+#define CODE_DCM_AorticAnnulusMinDiameter DSRBasicCodedEntry("131144", "DCM", "Aortic annulus min diameter")
+#define CODE_DCM_AorticAnnulusPerimeter DSRBasicCodedEntry("131145", "DCM", "Aortic annulus perimeter")
+#define CODE_DCM_AorticCalcificationVolume DSRBasicCodedEntry("131146", "DCM", "Aortic calcification volume")
+#define CODE_DCM_AorticCommissuresCalcificationSeverity DSRBasicCodedEntry("131147", "DCM", "Aortic commissures calcification severity")
+#define CODE_DCM_AorticRootHeight DSRBasicCodedEntry("131148", "DCM", "Aortic root height")
+#define CODE_DCM_AorticSinotubularJunctionDiameter DSRBasicCodedEntry("131149", "DCM", "Aortic sinotubular junction diameter")
+#define CODE_DCM_AorticSinusOfValsalvaArea DSRBasicCodedEntry("131150", "DCM", "Aortic sinus of valsalva area")
+#define CODE_DCM_AorticValveCoaptationLength DSRBasicCodedEntry("131152", "DCM", "Aortic valve coaptation length")
+#define CODE_DCM_AorticValveNoncoronaryLeafletIntercommissuralAngle DSRBasicCodedEntry("131153", "DCM", "Aortic valve noncoronary leaflet intercommissural angle")
+#define CODE_DCM_AorticValveRightLeafletIntercommissuralAngle DSRBasicCodedEntry("131154", "DCM", "Aortic valve right leaflet intercommissural angle")
+#define CODE_DCM_AorticValveLeftLeafletIntercommissuralAngle DSRBasicCodedEntry("131155", "DCM", "Aortic valve left leaflet intercommissural angle")
+#define CODE_DCM_AorticValveNoncoronaryLeafletIntercommissuralDistance DSRBasicCodedEntry("131156", "DCM", "Aortic valve noncoronary leaflet intercommissural distance")
+#define CODE_DCM_AorticValveRightLeafletIntercommissuralDistance DSRBasicCodedEntry("131157", "DCM", "Aortic valve right leaflet intercommissural distance")
+#define CODE_DCM_AorticValveLeftLeafletIntercommissuralDistance DSRBasicCodedEntry("131158", "DCM", "Aortic valve left leaflet intercommissural distance")
+#define CODE_DCM_AorticValveLeftCoronaryLeafletHeight DSRBasicCodedEntry("131159", "DCM", "Aortic valve left coronary leaflet height")
+#define CODE_DCM_AorticValveLeftCoronaryLeafletLength DSRBasicCodedEntry("131160", "DCM", "Aortic valve left coronary leaflet length")
+#define CODE_DCM_AorticValveNoncoronaryLeafletHeight DSRBasicCodedEntry("131161", "DCM", "Aortic valve noncoronary leaflet height")
+#define CODE_DCM_AorticValveNoncoronaryLeafletLength DSRBasicCodedEntry("131162", "DCM", "Aortic valve noncoronary leaflet length")
+#define CODE_DCM_AorticValveRightCoronaryLeafletHeight DSRBasicCodedEntry("131163", "DCM", "Aortic valve right coronary leaflet height")
+#define CODE_DCM_AorticValveRightCoronaryLeafletLength DSRBasicCodedEntry("131164", "DCM", "Aortic valve right coronary leaflet length")
+#define CODE_DCM_AscendingAortaDiameter DSRBasicCodedEntry("131165", "DCM", "Ascending Aorta diameter")
+#define CODE_DCM_LeftMainCoronaryOstiumHeight DSRBasicCodedEntry("131166", "DCM", "Left main coronary ostium height")
+#define CODE_DCM_LeftVentricularOutflowTractCalcificationSeverity DSRBasicCodedEntry("131167", "DCM", "Left ventricular outflow tract calcification severity")
+#define CODE_DCM_MaximumAorticPlaqueThickness DSRBasicCodedEntry("131168", "DCM", "Maximum aortic plaque thickness")
+#define CODE_DCM_RightCoronaryArteryOstiumHeight DSRBasicCodedEntry("131169", "DCM", "Right coronary artery ostium height")
+#define CODE_DCM_RightVentricleDiastolicMajorAxis DSRBasicCodedEntry("131170", "DCM", "Right ventricle diastolic major axis")
+#define CODE_DCM_RightVentricularDiastolicMidSegmentMinorAxis DSRBasicCodedEntry("131171", "DCM", "Right ventricular diastolic mid segment minor axis")
+#define CODE_DCM_RightVentricularDiastolicBasalMinorAxis DSRBasicCodedEntry("131172", "DCM", "Right ventricular diastolic basal minor axis")
+#define CODE_DCM_MitralAnteriorLeafletA1ScallopLength DSRBasicCodedEntry("131173", "DCM", "Mitral anterior leaflet A1 scallop length")
+#define CODE_DCM_MitralAnteriorLeafletA2ScallopLength DSRBasicCodedEntry("131174", "DCM", "Mitral anterior leaflet A2 scallop length")
+#define CODE_DCM_MitralAnteriorLeafletA3ScallopLength DSRBasicCodedEntry("131175", "DCM", "Mitral anterior leaflet A3 scallop length")
+#define CODE_DCM_MitralAnteriorLeafletArea DSRBasicCodedEntry("131176", "DCM", "Mitral anterior leaflet area")
+#define CODE_DCM_AortoMitralInterAnnularAngle DSRBasicCodedEntry("131177", "DCM", "Aorto-mitral inter annular angle")
+#define CODE_DCM_MitralCommissureDistance DSRBasicCodedEntry("131178", "DCM", "Mitral commissure distance")
+#define CODE_DCM_MitralTrigoneToTrigoneDistance DSRBasicCodedEntry("131179", "DCM", "Mitral trigone-to-trigone distance")
+#define CODE_DCM_MitralAnnularExcursion DSRBasicCodedEntry("131180", "DCM", "Mitral annular excursion")
+#define CODE_DCM_MitralAnnulusAnterolateralToPosteromedialDiameter DSRBasicCodedEntry("131181", "DCM", "Mitral annulus anterolateral to posteromedial diameter")
+#define CODE_DCM_MitralAnnulusAnteroposteriorDiameter DSRBasicCodedEntry("131182", "DCM", "Mitral annulus anteroposterior diameter")
+#define CODE_DCM_MitralAnnulusArea DSRBasicCodedEntry("131183", "DCM", "Mitral annulus area")
+#define CODE_DCM_MitralAnnulusCalcificationSeverity DSRBasicCodedEntry("131184", "DCM", "Mitral annulus calcification severity")
+#define CODE_DCM_MitralAnnulusCommissuralDiameter DSRBasicCodedEntry("131185", "DCM", "Mitral annulus commissural diameter")
+#define CODE_DCM_MitralAnnulusDiameterRatio DSRBasicCodedEntry("131186", "DCM", "Mitral annulus diameter ratio")
+#define CODE_DCM_MitralAnnulusHeight DSRBasicCodedEntry("131187", "DCM", "Mitral annulus height")
+#define CODE_DCM_MitralAnnulusNonplanarityAngle DSRBasicCodedEntry("131188", "DCM", "Mitral annulus nonplanarity angle")
+#define CODE_DCM_MitralAnnulusPerimeter DSRBasicCodedEntry("131189", "DCM", "Mitral annulus perimeter")
+#define CODE_DCM_MitralValveCoaptationLength DSRBasicCodedEntry("131190", "DCM", "Mitral valve coaptation length")
+#define CODE_DCM_MitralValveInterpapillaryDistance DSRBasicCodedEntry("131191", "DCM", "Mitral valve interpapillary distance")
+#define CODE_DCM_AnterolateralPapillaryMuscleToTheLeftTrigone DSRBasicCodedEntry("131192", "DCM", "Anterolateral papillary muscle to the left trigone")
+#define CODE_DCM_PosteromedialPapillaryMuscleToTheRightTrigone DSRBasicCodedEntry("131193", "DCM", "Posteromedial papillary muscle to the right trigone")
+#define CODE_DCM_MitralValveProlapseArea DSRBasicCodedEntry("131194", "DCM", "Mitral valve prolapse area")
+#define CODE_DCM_MitralValveProlapseVolume DSRBasicCodedEntry("131195", "DCM", "Mitral valve prolapse volume")
+#define CODE_DCM_MitralValveSegmentFlailGap DSRBasicCodedEntry("131196", "DCM", "Mitral valve segment flail gap")
+#define CODE_DCM_MitralValveSphericityIndex DSRBasicCodedEntry("131197", "DCM", "Mitral valve sphericity index")
+#define CODE_DCM_MitralValveTentingHeight DSRBasicCodedEntry("131198", "DCM", "Mitral valve tenting height")
+#define CODE_DCM_MitralValveTentingArea DSRBasicCodedEntry("131199", "DCM", "Mitral valve tenting area")
+#define CODE_DCM_MitralValveTentingSegmentHeightA1P1 DSRBasicCodedEntry("131200", "DCM", "Mitral valve tenting segment height A1-P1")
+#define CODE_DCM_MitralValveTentingSegmentHeightA2P2 DSRBasicCodedEntry("131201", "DCM", "Mitral valve tenting segment height A2-P2")
+#define CODE_DCM_MitralValveTentingSegmentHeightA3P3 DSRBasicCodedEntry("131202", "DCM", "Mitral valve tenting segment height A3-P3")
+#define CODE_DCM_PosteriorMitralValveLeafletArea DSRBasicCodedEntry("131203", "DCM", "Posterior mitral valve leaflet area")
+#define CODE_DCM_PosteriorMitralValveLeafletLength DSRBasicCodedEntry("131204", "DCM", "Posterior mitral valve leaflet length")
+#define CODE_DCM_PosteriorMitralValveP1LeafletScallopLength DSRBasicCodedEntry("131205", "DCM", "Posterior mitral valve P1 leaflet scallop length")
+#define CODE_DCM_PosteriorMitralValveP2LeafletScallopLength DSRBasicCodedEntry("131206", "DCM", "Posterior mitral valve P2 leaflet scallop length")
+#define CODE_DCM_PosteriorMitralValveP3LeafletScallopLength DSRBasicCodedEntry("131207", "DCM", "Posterior mitral valve P3 leaflet scallop length")
+#define CODE_DCM_TricuspidAnnulusArea DSRBasicCodedEntry("131208", "DCM", "Tricuspid annulus area")
+#define CODE_DCM_TricuspidAnnulusAreaDiastolicSystolicRatio DSRBasicCodedEntry("131209", "DCM", "Tricuspid annulus area diastolic systolic ratio")
+#define CODE_DCM_TricuspidAnnulusPerimeter DSRBasicCodedEntry("131210", "DCM", "Tricuspid annulus perimeter")
+#define CODE_DCM_TricuspidValveCoaptationLength DSRBasicCodedEntry("131211", "DCM", "Tricuspid valve coaptation length")
+#define CODE_DCM_TricuspidValveMajorAxisDiastole DSRBasicCodedEntry("131212", "DCM", "Tricuspid valve major axis diastole")
+#define CODE_DCM_TricuspidValveMinorAxis DSRBasicCodedEntry("131213", "DCM", "Tricuspid valve minor axis")
+#define CODE_DCM_TricuspidValveSphericityIndex DSRBasicCodedEntry("131214", "DCM", "Tricuspid valve sphericity index")
+#define CODE_DCM_TricuspidValveTentingHeight DSRBasicCodedEntry("131215", "DCM", "Tricuspid valve tenting height")
+#define CODE_DCM_TricuspidValveTentingVolume DSRBasicCodedEntry("131216", "DCM", "Tricuspid valve tenting volume")
+#define CODE_DCM_LeftAtrialAppendageClosureDeviceCircumference DSRBasicCodedEntry("131217", "DCM", "Left atrial appendage closure device circumference")
+#define CODE_DCM_LeftAtrialAppendageClosureDeviceCompressionRatio DSRBasicCodedEntry("131218", "DCM", "Left atrial appendage closure device compression ratio")
+#define CODE_DCM_LeftAtrialAppendageClosureDeviceDiameter DSRBasicCodedEntry("131219", "DCM", "Left atrial appendage closure device diameter")
+#define CODE_DCM_LeftAtrialAppendageClosureDeviceSize DSRBasicCodedEntry("131220", "DCM", "Left atrial appendage closure device size")
+#define CODE_DCM_LeftAtrialAppendageDepth DSRBasicCodedEntry("131221", "DCM", "Left atrial appendage depth")
+#define CODE_DCM_LeftAtrialAppendageLandingZoneMajorAxis DSRBasicCodedEntry("131222", "DCM", "Left atrial appendage landing zone major axis")
+#define CODE_DCM_LeftAtrialAppendageMajorAxis DSRBasicCodedEntry("131223", "DCM", "Left atrial appendage major axis")
+#define CODE_DCM_LeftAtrialAppendageMinorAxis DSRBasicCodedEntry("131224", "DCM", "Left atrial appendage minor axis")
+#define CODE_DCM_LeftAtrialAppendageOstiumPerimeter DSRBasicCodedEntry("131225", "DCM", "Left atrial appendage ostium perimeter")
+#define CODE_DCM_FemaleTypical DSRBasicCodedEntry("131230", "DCM", "Female-typical")
+#define CODE_DCM_MaleTypical DSRBasicCodedEntry("131231", "DCM", "Male-typical")
+#define CODE_DCM_Specified DSRBasicCodedEntry("131232", "DCM", "Specified")
+#define CODE_DCM_SubjectSexParametersForClinicalUseCategory DSRBasicCodedEntry("131233", "DCM", "Subject Sex Parameters for Clinical Use Category")
+#define CODE_DCM_SexParametersForClinicalUseCategoryComment DSRBasicCodedEntry("131234", "DCM", "Sex Parameters for Clinical Use Category Comment")
+#define CODE_DCM_SexParametersForClinicalUseCategoryReference DSRBasicCodedEntry("131235", "DCM", "Sex Parameters for Clinical Use Category Reference")
+#define CODE_DCM_VisualFieldKeyMeasurements DSRBasicCodedEntry("131240", "DCM", "Visual Field Key Measurements")
+#define CODE_DCM_OpticDiscKeyMeasurements DSRBasicCodedEntry("131241", "DCM", "Optic Disc Key Measurements")
+#define CODE_DCM_CircumpapillaryRetinalNerveFiberLayerKeyMeasurements DSRBasicCodedEntry("131242", "DCM", "Circumpapillary Retinal Nerve Fiber Layer Key Measurements")
+#define CODE_DCM_MacularThicknessKeyMeasurements DSRBasicCodedEntry("131243", "DCM", "Macular Thickness Key Measurements")
+#define CODE_DCM_GanglionCellLayerKeyMeasurements DSRBasicCodedEntry("131244", "DCM", "Ganglion Cell Layer Key Measurements")
+#define CODE_DCM_EndothelialCellCountKeyMeasurements DSRBasicCodedEntry("131245", "DCM", "Endothelial Cell Count Key Measurements")
+#define CODE_DCM_OphthalmicImageROIMeasurements DSRBasicCodedEntry("131246", "DCM", "Ophthalmic Image ROI Measurements")
+#define CODE_DCM_RepositionedROIOrGrid DSRBasicCodedEntry("131247", "DCM", "Repositioned ROI or grid")
+#define CODE_DCM_VisualFieldGlobalDeviationFromNormal DSRBasicCodedEntry("131248", "DCM", "Visual Field Global Deviation from Normal")
+#define CODE_DCM_VisualFieldLocalizedDeviationFromNormal DSRBasicCodedEntry("131249", "DCM", "Visual Field Localized Deviation From Normal")
+#define CODE_DCM_FixationFalsePositiveRatio DSRBasicCodedEntry("131250", "DCM", "Fixation false positive ratio")
+#define CODE_DCM_FixationFalsePositivePercent DSRBasicCodedEntry("131251", "DCM", "Fixation false positive percent")
+#define CODE_DCM_FixationFalseNegativeRatio DSRBasicCodedEntry("131252", "DCM", "Fixation false negative ratio")
+#define CODE_DCM_FixationFalseNegativePercent DSRBasicCodedEntry("131253", "DCM", "Fixation false negative percent")
+#define CODE_DCM_FixationLossesRatio DSRBasicCodedEntry("131254", "DCM", "Fixation losses ratio")
+#define CODE_DCM_AverageMacularThickness DSRBasicCodedEntry("131255", "DCM", "Average macular thickness")
+#define CODE_DCM_CupToDiscAreaRatio DSRBasicCodedEntry("131256", "DCM", "Cup to disc area ratio")
+#define CODE_DCM_CupToDiscRatioVertical DSRBasicCodedEntry("131257", "DCM", "Cup to disc ratio vertical")
+#define CODE_DCM_CupToDiscRatioHorizontal DSRBasicCodedEntry("131258", "DCM", "Cup to disc ratio horizontal")
+#define CODE_DCM_NeuroretinalRimArea DSRBasicCodedEntry("131259", "DCM", "Neuroretinal rim area")
+#define CODE_DCM_NeuroretinalRimWidth DSRBasicCodedEntry("131260", "DCM", "Neuroretinal rim width")
+#define CODE_DCM_OpticCupArea DSRBasicCodedEntry("131261", "DCM", "Optic cup area")
+#define CODE_DCM_OpticDiscArea DSRBasicCodedEntry("131262", "DCM", "Optic disc area")
+#define CODE_DCM_OpticCupVolume DSRBasicCodedEntry("131263", "DCM", "Optic cup volume")
+#define CODE_DCM_RNFLAverageThickness DSRBasicCodedEntry("131264", "DCM", "RNFL average thickness")
+#define CODE_DCM_RNFLInferiorSectorThickness DSRBasicCodedEntry("131265", "DCM", "RNFL inferior sector thickness")
+#define CODE_DCM_RNFLSuperiorSectorThickness DSRBasicCodedEntry("131266", "DCM", "RNFL superior sector thickness")
+#define CODE_DCM_RNFLTemporalSectorThickness DSRBasicCodedEntry("131267", "DCM", "RNFL temporal sector thickness")
+#define CODE_DCM_RNFLNasalSectorThickness DSRBasicCodedEntry("131268", "DCM", "RNFL nasal sector thickness")
+#define CODE_DCM_RNFLNasalSuperiorSectorThickness DSRBasicCodedEntry("131269", "DCM", "RNFL nasal-superior sector thickness")
+#define CODE_DCM_RNFLNasalInferiorSectorThickness DSRBasicCodedEntry("131270", "DCM", "RNFL nasal-inferior sector thickness")
+#define CODE_DCM_RNFLTemporalInferiorSectorThickness DSRBasicCodedEntry("131271", "DCM", "RNFL temporal-inferior sector thickness")
+#define CODE_DCM_RNFLTemporalSuperiorSectorThickness DSRBasicCodedEntry("131272", "DCM", "RNFL temporal-superior sector thickness")
+#define CODE_DCM_RetinalNerveFiberLayerSymmetry DSRBasicCodedEntry("131273", "DCM", "Retinal nerve fiber layer symmetry")
+#define CODE_DCM_RetinalROIWidth DSRBasicCodedEntry("131274", "DCM", "Retinal ROI width")
+#define CODE_DCM_RetinalROIHeight DSRBasicCodedEntry("131275", "DCM", "Retinal ROI height")
+#define CODE_DCM_RNFLClockfacePosition1Thickness DSRBasicCodedEntry("131276", "DCM", "RNFL clockface position 1 thickness")
+#define CODE_DCM_RNFLClockfacePosition2Thickness DSRBasicCodedEntry("131277", "DCM", "RNFL clockface position 2 thickness")
+#define CODE_DCM_RNFLClockfacePosition3Thickness DSRBasicCodedEntry("131278", "DCM", "RNFL clockface position 3 thickness")
+#define CODE_DCM_RNFLClockfacePosition4Thickness DSRBasicCodedEntry("131279", "DCM", "RNFL clockface position 4 thickness")
+#define CODE_DCM_RNFLClockfacePosition5Thickness DSRBasicCodedEntry("131280", "DCM", "RNFL clockface position 5 thickness")
+#define CODE_DCM_RNFLClockfacePosition6Thickness DSRBasicCodedEntry("131281", "DCM", "RNFL clockface position 6 thickness")
+#define CODE_DCM_RNFLClockfacePosition7Thickness DSRBasicCodedEntry("131282", "DCM", "RNFL clockface position 7 thickness")
+#define CODE_DCM_RNFLClockfacePosition8Thickness DSRBasicCodedEntry("131283", "DCM", "RNFL clockface position 8 thickness")
+#define CODE_DCM_RNFLClockfacePosition9Thickness DSRBasicCodedEntry("131284", "DCM", "RNFL clockface position 9 thickness")
+#define CODE_DCM_RNFLClockfacePosition10Thickness DSRBasicCodedEntry("131285", "DCM", "RNFL clockface position 10 thickness")
+#define CODE_DCM_RNFLClockfacePosition11Thickness DSRBasicCodedEntry("131286", "DCM", "RNFL clockface position 11 thickness")
+#define CODE_DCM_RNFLClockfacePosition12Thickness DSRBasicCodedEntry("131287", "DCM", "RNFL clockface position 12 thickness")
+#define CODE_DCM_AverageGanglionCellThickness DSRBasicCodedEntry("131288", "DCM", "Average ganglion cell thickness")
+#define CODE_DCM_MinimumGanglionCellThickness DSRBasicCodedEntry("131289", "DCM", "Minimum ganglion cell thickness")
+#define CODE_DCM_AverageGanglionCellThicknessSuperiorSector DSRBasicCodedEntry("131290", "DCM", "Average ganglion cell thickness superior sector")
+#define CODE_DCM_AverageGanglionCellThicknessNasalSuperiorSector DSRBasicCodedEntry("131291", "DCM", "Average ganglion cell thickness nasal-superior sector")
+#define CODE_DCM_AverageGanglionCellThicknessNasalSector DSRBasicCodedEntry("131292", "DCM", "Average ganglion cell thickness nasal sector")
+#define CODE_DCM_AverageGanglionCellThicknessNasalInferiorSector DSRBasicCodedEntry("131293", "DCM", "Average ganglion cell thickness nasal-inferior sector")
+#define CODE_DCM_AverageGanglionCellThicknessInferiorSector DSRBasicCodedEntry("131294", "DCM", "Average ganglion cell thickness inferior sector")
+#define CODE_DCM_AverageGanglionCellThicknessTemporalInferiorSector DSRBasicCodedEntry("131295", "DCM", "Average ganglion cell thickness temporal-inferior sector")
+#define CODE_DCM_AverageGanglionCellThicknessTemporalSector DSRBasicCodedEntry("131296", "DCM", "Average ganglion cell thickness temporal sector")
+#define CODE_DCM_AverageGanglionCellThicknessTemporalSuperiorSector DSRBasicCodedEntry("131297", "DCM", "Average ganglion cell thickness temporal-superior sector")
+#define CODE_DCM_AverageGanglionCellThicknessInPosteriorPoleGrid DSRBasicCodedEntry("131298", "DCM", "Average ganglion cell thickness in posterior pole grid")
+#define CODE_DCM_GanglionCellAndInnerPlexiformLayers DSRBasicCodedEntry("131299", "DCM", "Ganglion cell and inner plexiform layers")
+#define CODE_DCM_GanglionCellComplex DSRBasicCodedEntry("131300", "DCM", "Ganglion cell complex")
+#define CODE_DCM_SemicircularSectors DSRBasicCodedEntry("131301", "DCM", "Semicircular sectors")
+#define CODE_DCM_QuadrantSectors DSRBasicCodedEntry("131302", "DCM", "Quadrant sectors")
+#define CODE_DCM_SNITRectangularSectors DSRBasicCodedEntry("131303", "DCM", "SNIT rectangular sectors")
+#define CODE_DCM_EllipticalAnnulusSectors DSRBasicCodedEntry("131304", "DCM", "Elliptical annulus sectors")
+#define CODE_DCM_GarwayHeathSectors DSRBasicCodedEntry("131305", "DCM", "Garway-Heath sectors")
+#define CODE_DCM_QuadrantOctantSectors DSRBasicCodedEntry("131306", "DCM", "Quadrant-octant sectors")
+#define CODE_DCM_PosteriorPole8x8Grid DSRBasicCodedEntry("131307", "DCM", "Posterior pole 8x8 grid")
+#define CODE_DCM_RNFLClockfaceMethod DSRBasicCodedEntry("131308", "DCM", "RNFL Clockface Method")
+#define CODE_DCM_EndothelialCellDensity DSRBasicCodedEntry("131309", "DCM", "Endothelial cell density")
+#define CODE_DCM_GeographicAtrophyArea DSRBasicCodedEntry("131310", "DCM", "Geographic atrophy area")
+#define CODE_DCM_PlanMeetsPrescription DSRBasicCodedEntry("131315", "DCM", "Plan meets prescription")
+#define CODE_DCM_PlanQAPassed DSRBasicCodedEntry("131316", "DCM", "Plan QA passed")
+#define CODE_DCM_LinearBoltzmannTransportEquation DSRBasicCodedEntry("131320", "DCM", "Linear Boltzmann Transport Equation")
+#define CODE_DCM_PencilBeamConvolution DSRBasicCodedEntry("131321", "DCM", "Pencil Beam Convolution")
+#define CODE_DCM_TMRAndOARRatios DSRBasicCodedEntry("131322", "DCM", "TMR and OAR Ratios")
+#define CODE_DCM_AAPMTG43 DSRBasicCodedEntry("131323", "DCM", "AAPM TG-43")
+#define CODE_DCM_ConvolutionSuperposition DSRBasicCodedEntry("131324", "DCM", "Convolution Superposition")
+#define CODE_DCM_NumberOfHistories DSRBasicCodedEntry("131325", "DCM", "Number of Histories")
+#define CODE_DCM_AcceptableUncertaintyInDoseResult DSRBasicCodedEntry("131326", "DCM", "Acceptable Uncertainty in Dose Result")
+#define CODE_DCM_CalibrationIntendedDoseIndex DSRBasicCodedEntry("131330", "DCM", "Calibration Intended Dose Index")
+#define CODE_DCM_CalibrationIntendedAcquisitionProtocol DSRBasicCodedEntry("131331", "DCM", "Calibration Intended Acquisition Protocol")
+#define CODE_DCM_UltrasoundAttenuationImaging DSRBasicCodedEntry("131340", "DCM", "Ultrasound Attenuation Imaging")
+#define CODE_DCM_UltrasoundAttenuationCoefficient DSRBasicCodedEntry("131341", "DCM", "Ultrasound Attenuation Coefficient")
+#define CODE_DCM_MeanUltrasoundAttenuationCoefficient DSRBasicCodedEntry("131342", "DCM", "Mean Ultrasound Attenuation Coefficient")
+#define CODE_DCM_MedianUltrasoundAttenuationCoefficient DSRBasicCodedEntry("131343", "DCM", "Median Ultrasound Attenuation Coefficient")
+#define CODE_DCM_StandardDeviationOfUltrasoundAttenuationCoefficient DSRBasicCodedEntry("131344", "DCM", "Standard Deviation of Ultrasound Attenuation Coefficient")
+#define CODE_DCM_InterquartileRangeOfUltrasoundAttenuationCoefficient DSRBasicCodedEntry("131345", "DCM", "Interquartile Range of Ultrasound Attenuation Coefficient")
+#define CODE_DCM_InterquartileRangeToMedianRatioOfUltrasoundAttenCoeff DSRBasicCodedEntry("131346", "DCM", "Interquartile Range to Median Ratio of Ultrasound Atten Coeff")
+#define CODE_DCM_CardiacAxisAngle DSRBasicCodedEntry("131350", "DCM", "Cardiac Axis Angle")
+#define CODE_DCM_DVSWavePeakVelocity DSRBasicCodedEntry("131351", "DCM", "DV S-wave peak velocity")
+#define CODE_DCM_DVAWavePeakVelocity DSRBasicCodedEntry("131352", "DCM", "DV a-wave peak velocity")
+#define CODE_DCM_DVPreloadIndex DSRBasicCodedEntry("131353", "DCM", "DV preload index")
+#define CODE_DCM_DVSA DSRBasicCodedEntry("131354", "DCM", "DV S/a")
+#define CODE_DCM_RejectionWithdrawn DSRBasicCodedEntry("131360", "DCM", "Rejection Withdrawn")
+#define CODE_DCM_FetalAnatomySurvey DSRBasicCodedEntry("131370", "DCM", "Fetal Anatomy Survey")
+#define CODE_DCM_AbdominalAttachmentOfUmbilicalCord DSRBasicCodedEntry("131371", "DCM", "Abdominal attachment of umbilical cord")
+#define CODE_DCM_RetronasalTriangle DSRBasicCodedEntry("131372", "DCM", "Retronasal triangle")
+#define CODE_DCM_MidsagittalFacialProfile DSRBasicCodedEntry("131373", "DCM", "Midsagittal facial profile")
+#define CODE_DCM_CardiacAxis DSRBasicCodedEntry("131374", "DCM", "Cardiac axis")
+#define CODE_DCM_JugularLymphaticSac DSRBasicCodedEntry("131375", "DCM", "Jugular lymphatic sac")
+#define CODE_DCM_TransthalamicCoronalView DSRBasicCodedEntry("131376", "DCM", "Transthalamic coronal view")
+#define CODE_DCM_MidsagittalView DSRBasicCodedEntry("131377", "DCM", "Midsagittal view")
+#define CODE_DCM_HighShortAxisView DSRBasicCodedEntry("131378", "DCM", "High short axis view")
+#define CODE_DCM_AntegradeDuctusVenosus DSRBasicCodedEntry("131379", "DCM", "Antegrade ductus venosus")
+#define CODE_DCM_ISUOG1stTrimester2023 DSRBasicCodedEntry("131380", "DCM", "ISUOG 1st Trimester 2023")
+#define CODE_DCM_ISUOG2ndTrimester2022 DSRBasicCodedEntry("131381", "DCM", "ISUOG 2nd Trimester 2022")
+#define CODE_DCM_ISUOG3rdTrimester2024 DSRBasicCodedEntry("131382", "DCM", "ISUOG 3rd Trimester 2024")
+#define CODE_DCM_JSUMFetalMorphology2021 DSRBasicCodedEntry("131383", "DCM", "JSUM Fetal Morphology 2021")
+#define CODE_DCM_JDMSFetalAnatomy2014 DSRBasicCodedEntry("131384", "DCM", "JDMS Fetal Anatomy 2014")
#endif
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file with NCI Thesaurus Code Definitions (Coding Scheme "NCIt")
*
- * Generated automatically from DICOM PS 3.16-2024e
- * File created on 2024-11-16 10:17:31 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 11:52:23 by J. Riesmeier
*
*/
* code definitions *
*--------------------*/
-// total number of codes: 51
+// total number of codes: 61
// - retired: 0
// - no name: 0
// - not unique: 0
#define CODE_NCIt_Sarcosine_C11 DSRBasicCodedEntry("C122684", "NCIt", "Sarcosine C^11^")
#define CODE_NCIt_IrreversibleElectroporation DSRBasicCodedEntry("C131483", "NCIt", "Irreversible electroporation")
#define CODE_NCIt_4Kscore DSRBasicCodedEntry("C142184", "NCIt", "4Kscore")
+#define CODE_NCIt_Pembrolizumab_89Zr DSRBasicCodedEntry("C148167", "NCIt", "Pembrolizumab ^89^Zr")
#define CODE_NCIt_SoftTissueSarcoma_excludingRhabdomyosarcoma DSRBasicCodedEntry("C148457", "NCIt", "Soft tissue sarcoma, excluding rhabdomyosarcoma")
#define CODE_NCIt_Cryoablation DSRBasicCodedEntry("C15215", "NCIt", "Cryoablation")
+#define CODE_NCIt_PAXgeneTissueSystem DSRBasicCodedEntry("C185113", "NCIt", "PAXgene Tissue System")
#define CODE_NCIt_166Holmium DSRBasicCodedEntry("C1943", "NCIt", "^166^Holmium")
#define CODE_NCIt_MouseMammaryFatPad DSRBasicCodedEntry("C22550", "NCIt", "Mouse mammary fat pad")
#define CODE_NCIt_Middle DSRBasicCodedEntry("C25569", "NCIt", "Middle")
#define CODE_NCIt_Experience DSRBasicCodedEntry("C54627", "NCIt", "Experience")
#define CODE_NCIt_Reviewer DSRBasicCodedEntry("C54634", "NCIt", "Reviewer")
#define CODE_NCIt_Ion DSRBasicCodedEntry("C597", "NCIt", "Ion")
+#define CODE_NCIt_FluoroazomycinArabinoside_F18 DSRBasicCodedEntry("C62520", "NCIt", "Fluoroazomycin arabinoside F^18^")
#define CODE_NCIt_AdLibitum DSRBasicCodedEntry("C64636", "NCIt", "ad libitum")
#define CODE_NCIt_ActivitySession DSRBasicCodedEntry("C67447", "NCIt", "Activity Session")
#define CODE_NCIt_FocusedUltrasoundAblation DSRBasicCodedEntry("C68681", "NCIt", "Focused ultrasound ablation")
#define CODE_NCIt_UnitConversionFactor DSRBasicCodedEntry("C70774", "NCIt", "Unit Conversion Factor")
#define CODE_NCIt_MedicalProductExpirationDate DSRBasicCodedEntry("C70854", "NCIt", "Medical Product Expiration Date")
+#define CODE_NCIt_FitzpatrickSkinTypeI DSRBasicCodedEntry("C74569", "NCIt", "Fitzpatrick Skin Type I")
+#define CODE_NCIt_FitzpatrickSkinTypeII DSRBasicCodedEntry("C74570", "NCIt", "Fitzpatrick Skin Type II")
+#define CODE_NCIt_FitzpatrickSkinTypeIII DSRBasicCodedEntry("C74571", "NCIt", "Fitzpatrick Skin Type III")
+#define CODE_NCIt_FitzpatrickSkinTypeIV DSRBasicCodedEntry("C74572", "NCIt", "Fitzpatrick Skin Type IV")
+#define CODE_NCIt_FitzpatrickSkinTypeV DSRBasicCodedEntry("C74573", "NCIt", "Fitzpatrick Skin Type V")
+#define CODE_NCIt_FitzpatrickSkinTypeVI DSRBasicCodedEntry("C74574", "NCIt", "Fitzpatrick Skin Type VI")
#define CODE_NCIt_CardiotonicAgent DSRBasicCodedEntry("C78322", "NCIt", "Cardiotonic agent")
#define CODE_NCIt_NonEnhancingLesion DSRBasicCodedEntry("C81175", "NCIt", "Non-Enhancing Lesion")
#define CODE_NCIt_ImagingRegionOfInterest DSRBasicCodedEntry("C85402", "NCIt", "Imaging Region of Interest")
#define CODE_NCIt_HousingHumidity DSRBasicCodedEntry("C90395", "NCIt", "Housing humidity")
#define CODE_NCIt_LightCycle DSRBasicCodedEntry("C90419", "NCIt", "Light cycle")
#define CODE_NCIt_WaterDelivery DSRBasicCodedEntry("C90486", "NCIt", "Water delivery")
+#define CODE_NCIt_2Thymidine_C11 DSRBasicCodedEntry("C90936", "NCIt", "2-Thymidine C^11^")
#define CODE_NCIt_Dosimetrist DSRBasicCodedEntry("C93176", "NCIt", "Dosimetrist")
#define CODE_NCIt_Abnormality DSRBasicCodedEntry("C9440", "NCIt", "Abnormality")
#define CODE_NCIt_ReferenceRegion DSRBasicCodedEntry("C94970", "NCIt", "Reference Region")
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Header file with UMLS Code Definitions (Coding Scheme "UMLS")
*
- * Generated automatically from DICOM PS 3.16-2024e
- * File created on 2024-11-16 10:17:31 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 11:52:22 by J. Riesmeier
*
*/
* code definitions *
*--------------------*/
-// total number of codes: 51
+// total number of codes: 60
// - retired: 0
// - no name: 0
// - not unique: 0
#define CODE_UMLS_Duration DSRBasicCodedEntry("C0449238", "UMLS", "Duration")
#define CODE_UMLS_InfantOfMotherWithGestationalDiabetes DSRBasicCodedEntry("C0456029", "UMLS", "Infant of mother with gestational diabetes")
#define CODE_UMLS_CoefficientOfVariance DSRBasicCodedEntry("C0681921", "UMLS", "Coefficient of Variance")
+#define CODE_UMLS_HeartSize DSRBasicCodedEntry("C0744689", "UMLS", "Heart size")
+#define CODE_UMLS_PercutaneousClosureOfAtrialSeptalDefect DSRBasicCodedEntry("C0844084", "UMLS", "Percutaneous closure of atrial septal defect")
#define CODE_UMLS_ManufacturerName DSRBasicCodedEntry("C0947322", "UMLS", "Manufacturer Name")
#define CODE_UMLS_Intern DSRBasicCodedEntry("C1144859", "UMLS", "Intern")
#define CODE_UMLS_ConsultingPhysician DSRBasicCodedEntry("C1441532", "UMLS", "Consulting Physician")
#define CODE_UMLS_Referring DSRBasicCodedEntry("C1709880", "UMLS", "Referring")
#define CODE_UMLS_Variance DSRBasicCodedEntry("C1711260", "UMLS", "Variance")
#define CODE_UMLS_Sonographer DSRBasicCodedEntry("C1954848", "UMLS", "Sonographer")
+#define CODE_UMLS_AorticSinusOfValsalvaDiameter DSRBasicCodedEntry("C2059455", "UMLS", "Aortic sinus of valsalva diameter")
+#define CODE_UMLS_AorticAnnulusArea DSRBasicCodedEntry("C2059685", "UMLS", "Aortic annulus area")
#define CODE_UMLS_MobileSkinLesion DSRBasicCodedEntry("C2071496", "UMLS", "Mobile skin lesion")
#define CODE_UMLS_Neuroradiology DSRBasicCodedEntry("C2183225", "UMLS", "Neuroradiology")
#define CODE_UMLS_InverseRatioVentilation DSRBasicCodedEntry("C2223982", "UMLS", "Inverse ratio ventilation")
#define CODE_UMLS_RootMeanSquare DSRBasicCodedEntry("C2347976", "UMLS", "Root Mean Square")
#define CODE_UMLS_TimePoint DSRBasicCodedEntry("C2348792", "UMLS", "Time Point")
#define CODE_UMLS_Edotreotide_Ga68 DSRBasicCodedEntry("C2713594", "UMLS", "Edotreotide Ga^68^")
+#define CODE_UMLS_ImplantationOfMitralValveLeafletClip DSRBasicCodedEntry("C2921037", "UMLS", "Implantation of mitral valve leaflet clip")
#define CODE_UMLS_FluoropropylDihydrotetrabenazine_F18 DSRBasicCodedEntry("C2934038", "UMLS", "Fluoropropyl-dihydrotetrabenazine F^18^")
#define CODE_UMLS_ISO1_F18 DSRBasicCodedEntry("C2981788", "UMLS", "ISO-1 F^18^")
#define CODE_UMLS_RadiationPhysicist DSRBasicCodedEntry("C2985483", "UMLS", "Radiation Physicist")
+#define CODE_UMLS_LeftAtrialAppendageOcclusion DSRBasicCodedEntry("C3275093", "UMLS", "Left atrial appendage occlusion")
+#define CODE_UMLS_IntoleranceToAnticoagulation DSRBasicCodedEntry("C3468959", "UMLS", "Intolerance to anticoagulation")
#define CODE_UMLS_Pretreatment DSRBasicCodedEntry("C3539075", "UMLS", "Pretreatment")
#define CODE_UMLS_DistalPhalanx DSRBasicCodedEntry("C3669027", "UMLS", "Distal phalanx")
#define CODE_UMLS_RoomAir DSRBasicCodedEntry("C3846005", "UMLS", "Room air")
+#define CODE_UMLS_LeftAtrialDilation DSRBasicCodedEntry("C4015487", "UMLS", "Left atrial dilation")
#define CODE_UMLS_THK5351_F18 DSRBasicCodedEntry("C4279748", "UMLS", "THK5351 F^18^")
#define CODE_UMLS_MK6240_F18 DSRBasicCodedEntry("C4506764", "UMLS", "MK-6240 F^18^")
#define CODE_UMLS_UCBJ_C11 DSRBasicCodedEntry("C4506788", "UMLS", "UCB-J C^11^")
#define CODE_UMLS_THK5317_F18 DSRBasicCodedEntry("C4550127", "UMLS", "THK5317 F^18^")
+#define CODE_UMLS_PI2620_F18 DSRBasicCodedEntry("C5433257", "UMLS", "PI-2620 F^18^")
#define CODE_UMLS_MiddleEasternOrNorthAfrican DSRBasicCodedEntry("C5690844", "UMLS", "Middle Eastern or North African")
#endif
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* Value is increased automatically by 1 after a new entry has been added.
* @param flags flag used to customize the output (see DSRTypes::HF_xxx)
* @param urlPrefix optional URL prefix used for hyperlink to referenced composite object
+ ** @note Please note that using parameter 'urlPrefix' can lead to security issues, as an
+ * attacker could misuse it to potentially inject dangerous content into the HTML/XHTML
+ * output. The value of this parameter is not checked. This is also true for derived
+ * classes.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition renderHTML(STD_NAMESPACE ostream &docStream,
/*
*
- * Copyright (C) 2015-2016, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
return MappingResource;
}
+ /** get context group keyword
+ ** @return keyword of the context group (might be empty)
+ */
+ inline const OFString &getKeyword() const
+ {
+ return Keyword;
+ }
+
/** get context group version (optional)
** @return version of the context group (might be empty)
*/
/** constructor
** @param contextIdentifier identifier of the context group
* @param mappingResource mapping resource that defines the context group
+ * @param contextGroupKeyword keyword of the context group (optional)
* @param contextGroupVersion version of the context group (optional)
* @param contextGroupUID unique identifier of the context group (optional)
* @param selectedValue coded entry to be selected as the current value
*/
DSRContextGroup(const OFString &contextIdentifier,
const OFString &mappingResource,
+ const OFString &contextGroupKeyword = "",
const OFString &contextGroupVersion = "",
const OFString &contextGroupUID = "",
const DSRCodedEntryValue &selectedValue = DSRCodedEntryValue());
const OFString Identifier;
/// mapping resource (VR=CS, mandatory)
const OFString MappingResource;
+ /// context group keyword (optional)
+ const OFString Keyword;
/// context group version (VR=DT, optional)
const OFString Version;
/// context group UID (VR=UI, optional)
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/dcmsr/dsrrefin.h"
#include "dcmtk/dcmsr/dsrcsidl.h"
+#include "dcmtk/dcmdata/dcvras.h"
#include "dcmtk/dcmdata/dcvrcs.h"
#include "dcmtk/dcmdata/dcvrda.h"
#include "dcmtk/dcmdata/dcvrds.h"
* objects. If NULL, the default URL prefix is used, which is
* defined by DEFAULT_HTML_HYPERLINK_PREFIX_FOR_COMPOSITE_OBJECTS
* (http://localhost/dicom.cgi).
+ ** @note Please note that using the parameter 'styleSheet' or 'urlPrefix' can lead to
+ * security issues, as an attacker could misuse them to potentially inject dangerous
+ * content into the HTML/XHTML output. The values passed to these parameters are not
+ * checked, neither the URL and prefix nor the content of the specified CSS file.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition renderHTML(STD_NAMESPACE ostream &stream,
virtual OFCondition getPatientSex(OFString &value,
const signed long pos = 0) const;
+ /** get patient's age
+ ** @param value reference to variable in which the value should be stored
+ * @param pos index of the value to get (0..vm-1), -1 for all components
+ ** @return status, EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition getPatientAge(OFString &value,
+ const signed long pos = 0) const;
+
/** get patient's size
** @param value reference to variable in which the value should be stored
* @param pos index of the value to get (0..vm-1), -1 for all components
virtual OFCondition setPatientSex(const OFString &value,
const OFBool check = OFTrue);
+ /** set patient's age
+ ** @param value value to be set (single value only) or "" for no value
+ * @param check check 'value' for conformance with VR (AS) and VM (1) if enabled
+ ** @return status, EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition setPatientAge(const OFString &value,
+ const OFBool check = OFTrue);
+
/** set patient's size
** @param value value to be set (single value only) or "" for no value
* @param check check 'value' for conformance with VR (DS) and VM (1) if enabled
/** create a new document.
* A new SOP instance is only created if the current document type was valid/supported.
- * Please note that the current document is deleted (cleared).
+ * Please note that the current document is deleted (cleared) by this method.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition createNewDocument();
/** create a new document of the specified type.
* A new SOP instance is only created if the current document type was valid/supported.
- * Please note that the current document is deleted by this method.
+ * Please note that the current document is deleted (cleared) by this method.
** @param documentType type of the new SR document (see DSRTypes::E_DocumentType)
** @return status, EC_Normal if successful, an error code otherwise
*/
// --- Patient Study Module (U) ---
+ /// Patient's Age: (AS, 1, 3)
+ DcmAgeString PatientAge;
/// Patient's Size: (DS, 1, 3)
DcmDecimalString PatientSize;
/// Patient's Weight: (DS, 1, 3)
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* @param flags flag used to customize the output (see DSRTypes::HF_xxx)
* @param urlPrefix optional URL prefix used for hyperlinks to referenced composite
* objects. If NULL, the default URL prefix is used.
+ ** @note Please note that using parameter 'urlPrefix' can lead to security issues, as an
+ * attacker could misuse it to potentially inject dangerous content into the HTML/XHTML
+ * output. The value of this parameter is not checked. This is also true for derived
+ * classes.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition renderHTML(STD_NAMESPACE ostream &docStream,
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* @param flags optional flag used to customize the output (see DSRTypes::HF_xxx)
* @param urlPrefix optional URL prefix used for hyperlinks to referenced composite
* objects. If NULL, the default URL prefix is used.
+ ** @note Please note that using parameter 'urlPrefix' can lead to security issues, as an
+ * attacker could misuse it to potentially inject dangerous content into the HTML/XHTML
+ * output. The value of this parameter is not checked.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition renderHTML(STD_NAMESPACE ostream &docStream,
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFBool isSegmentation() const;
+ /** check whether an icon image is associated with this image reference.
+ * This method does not check whether the icon image is valid.
+ ** @return OFTrue if image reference has an icon image, OFFalse otherwise
+ */
+ virtual OFBool hasIconImage() const;
+
/** print image reference.
* The output of a typical image reference value looks like this: (CT image,"1.2.3") or
* (CT image,"1.2.3"),(GSPS,"1.2.3.4") if a presentation state is present.
* If the SOP class UID is unknown, the UID is printed instead of the related name.
* Also, the list of referenced frame/segment numbers is shown, but not the two UIDs of
- * the real world value mapping object (if referenced).
+ * the real world value mapping object (if referenced). The optional icon image is never
+ * shown.
** @param stream output stream to which the image reference value should be printed
* @param flags flag used to customize the output (see DSRTypes::PF_xxx)
** @return status, EC_Normal if successful, an error code otherwise
* has been added.
* @param flags flag used to customize the output (see DSRTypes::HF_xxx)
* @param urlPrefix optional URL prefix used for hyperlink to referenced composite object
+ ** @note Please note that using parameter 'urlPrefix' can lead to security issues, as an
+ * attacker could misuse it to potentially inject dangerous content into the HTML/XHTML
+ * output. The value of this parameter is not checked. This is also true for derived
+ * classes.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition renderHTML(STD_NAMESPACE ostream &docStream,
*/
OFCondition checkCurrentValue(const OFBool reportWarnings = OFFalse) const;
+ /** copy the given icon image to replace the currently stored one.
+ * The currently stored icon image is always deleted first.
+ * @param image pointer to the icon image to be copied (if not NULL)
+ */
+ void copyIconImage(DicomImage *image);
+
private:
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* These error codes can be used in addition to the general purpose
* codes defined in module dcmdata.
*/
-//@{
+///@{
/// error: the document type (SOP class UID) is unknown or not supported
extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_UnknownDocumentType;
/// error: cannot process document tree with included templates
extern DCMTK_DCMSR_EXPORT const OFConditionConst SR_EC_CannotProcessIncludedTemplates;
-//@}
+///@}
/*---------------------*
* These flags can be combined and passed to the read() methods.
* The 'shortcut' flags can be used for common combinations.
*/
- //@{
+ ///@{
/// read digital signatures from dataset
static const size_t RF_readDigitalSignatures;
/// show the currently processed content item (e.g. "1.2.3")
static const size_t RF_showCurrentlyProcessedItem;
- //@}
+ ///@}
/** @name renderHTML() flags
* Please note that only the 'external' flags can be used from outside
* this library. The 'shortcut' flags can be used for common combinations.
*/
- //@{
+ ///@{
/// external: never expand child nodes inline
static const size_t HF_neverExpandChildrenInline;
/// shortcut: filter all flags that are only used internally
static const size_t HF_internalUseOnly;
- //@}
+ ///@}
/** @name read/writeXML() flags
* These flags can be combined and passed to the read/writeXML() methods.
* The 'shortcut' flags can be used for common combinations.
*/
- //@{
+ ///@{
/// write: write all tags even if their value is empty
static const size_t XF_writeEmptyTags;
/// shortcut: combines all XF_xxxAsAttribute write flags (see above)
static const size_t XF_encodeEverythingAsAttribute;
- //@}
+ ///@}
/** @name print() flags
* These flags can be combined and passed to the print() methods.
* The 'shortcut' flags can be used for common combinations.
*/
- //@{
+ ///@{
/// print item position ("1.2.3") instead of line indentation
static const size_t PF_printItemPosition;
/// shortcut: print all codes (combines all PF_printXxxCodes flags, see above)
static const size_t PF_printAllCodes;
- //@}
+ ///@}
/** @name checkByReferenceRelationships() modes
* These modes can be combined and passed to the checkByReferenceRelationships() method.
*/
- //@{
+ ///@{
/// update the position string using the node ID
static const size_t CM_updatePositionString;
/// reset the reference target flag for all nodes
static const size_t CM_resetReferenceTargetFlag;
- //@}
+ ///@}
/** @name checkByReferenceRelationships() bit masks
* These bit masks are used to "filter" valid flags passed to checkByReferenceRelationships().
*/
- //@{
+ ///@{
/// bit mask (filter) for valid print flags (see PF_xxx)
static const size_t CB_maskPrintFlags;
/// bit mask (filter) for valid read flags (see RF_xxx)
static const size_t CB_maskReadFlags;
- //@}
+ ///@}
// --- type definitions ---
PT_MultipleVolumeRendering,
/// Variable Modality LUT Softcopy Presentation State (VML-SPS)
PT_VariableModalityLUT,
+ /// Waveform Presentation State (WPS)
+ PT_Waveform,
+ /// Waveform Acquisition Presentation State (WAPS)
+ PT_WaveformAcquisition,
/// internal type used to mark the last entry
- PT_last = PT_VariableModalityLUT
+ PT_last = PT_WaveformAcquisition
};
/** SR graphic types. Used for content item SCOORD.
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* Value is increased automatically by 1 after a new entry has been added.
* @param flags flag used to customize the output (see DSRTypes::HF_xxx)
* @param urlPrefix optional URL prefix used for hyperlink to referenced composite object
+ ** @note Please note that using parameter 'urlPrefix' can lead to security issues, as an
+ * attacker could misuse it to potentially inject dangerous content into the HTML/XHTML
+ * output. The value of this parameter is not checked. This is also true for derived
+ * classes.
** @return status, EC_Normal if successful, an error code otherwise
*/
virtual OFCondition renderHTML(STD_NAMESPACE ostream &docStream,
/*
*
- * Copyright (C) 2003-2024, OFFIS e.V.
+ * Copyright (C) 2003-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#define DSRXMLC_H
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
-
#include "dcmtk/dcmsr/dsdefine.h"
-
#include "dcmtk/ofstd/oftypes.h" /* for definition of OFBool */
+#include "dcmtk/ofstd/ofdiag.h"
#ifdef WITH_LIBXML
#define LIBXML_ATTR_FORMAT(fmt,args)
#endif
+// MacOS 15.5 defines some Clang specific pragmas in libxml header files.
+// Suppress warnings caused by these pragmas when compiling with GCC.
+#include DCMTK_DIAGNOSTIC_PUSH
+#include DCMTK_DIAGNOSTIC_IGNORE_CLANG_PRAGMAS_ON_GCC
#include <libxml/parser.h>
+#include DCMTK_DIAGNOSTIC_POP
+
#endif
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID100_QuantitativeDiagnosticImagingProcedure
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:09 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:43 by J. Riesmeier
*
*/
// general information on CID 100 (Quantitative Diagnostic Imaging Procedure)
#define CONTEXT_GROUP_NUMBER "100"
-#define CONTEXT_GROUP_VERSION "20230630"
+#define CONTEXT_GROUP_KEYWORD "QuantitativeDiagnosticImagingProcedure"
+#define CONTEXT_GROUP_VERSION "20250122"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.998"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID100_QuantitativeDiagnosticImagingProcedure::CID100_QuantitativeDiagnosticImagingProcedure(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID100_QuantitativeDiagnosticImagingProcedure::CID100_QuantitativeDiagnosticImagingProcedure(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
Codes->insert(OFMake_pair(PETCT_METImagingOfWholeBody, DSRBasicCodedEntry("764704008", "SCT", "PET/CT MET imaging of whole body")));
Codes->insert(OFMake_pair(CTPerfusionHeadWithContrastIV, DSRBasicCodedEntry("39142-5", "LN", "CT perfusion head with contrast IV")));
Codes->insert(OFMake_pair(SPECTBrain, DSRBasicCodedEntry("39632-5", "LN", "SPECT brain")));
- Codes->insert(OFMake_pair(NMHeadPerfusionBrainPET_CT_AV45, DSRBasicCodedEntry("RPID5427", "RADLEX", "NM head perfusion brain PET-CT AV-45")));
}
/* should never be NULL */
return *Codes;
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID10013_CTAcquisitionType
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:25 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:57 by J. Riesmeier
*
*/
// general information on CID 10013 (CT Acquisition Type)
#define CONTEXT_GROUP_NUMBER "10013"
+#define CONTEXT_GROUP_KEYWORD "CTAcquisitionType"
#define CONTEXT_GROUP_VERSION "20160314"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.545"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID10013_CTAcquisitionType::CID10013_CTAcquisitionType(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID10013_CTAcquisitionType::CID10013_CTAcquisitionType(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID10033_CTReconstructionAlgorithm
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:26 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:58 by J. Riesmeier
*
*/
// general information on CID 10033 (CT Reconstruction Algorithm)
#define CONTEXT_GROUP_NUMBER "10033"
+#define CONTEXT_GROUP_KEYWORD "CTReconstructionAlgorithm"
#define CONTEXT_GROUP_VERSION "20130207"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.958"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID10033_CTReconstructionAlgorithm::CID10033_CTReconstructionAlgorithm(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID10033_CTReconstructionAlgorithm::CID10033_CTReconstructionAlgorithm(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID11_AdministrationRoute
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:06 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:40 by J. Riesmeier
*
*/
// general information on CID 11 (Administration Route)
#define CONTEXT_GROUP_NUMBER "11"
+#define CONTEXT_GROUP_KEYWORD "AdministrationRoute"
#define CONTEXT_GROUP_VERSION "20240611"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.9"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID11_AdministrationRoute::CID11_AdministrationRoute(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID11_AdministrationRoute::CID11_AdministrationRoute(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID218_QuantitativeImageFeature
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:10 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:44 by J. Riesmeier
*
*/
// general information on CID 218 (Quantitative Image Feature)
#define CONTEXT_GROUP_NUMBER "218"
+#define CONTEXT_GROUP_KEYWORD "QuantitativeImageFeature"
#define CONTEXT_GROUP_VERSION "20200920"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.1269"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID218_QuantitativeImageFeature::CID218_QuantitativeImageFeature(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID218_QuantitativeImageFeature::CID218_QuantitativeImageFeature(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID244_Laterality
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:11 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:45 by J. Riesmeier
*
*/
// general information on CID 244 (Laterality)
#define CONTEXT_GROUP_NUMBER "244"
+#define CONTEXT_GROUP_KEYWORD "Laterality"
#define CONTEXT_GROUP_VERSION "20030108"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.37"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID244_Laterality::CID244_Laterality(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID244_Laterality::CID244_Laterality(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID247_LateralityLeftRightOnly
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:12 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:45 by J. Riesmeier
*
*/
// general information on CID 247 (Laterality Left-Right Only)
#define CONTEXT_GROUP_NUMBER "247"
+#define CONTEXT_GROUP_KEYWORD "LateralityLeftRightOnly"
#define CONTEXT_GROUP_VERSION "20190524"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.1284"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID247_LateralityLeftRightOnly::CID247_LateralityLeftRightOnly(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID247_LateralityLeftRightOnly::CID247_LateralityLeftRightOnly(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID29_AcquisitionModality
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:07 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:41 by J. Riesmeier
*
*/
// general information on CID 29 (Acquisition Modality)
#define CONTEXT_GROUP_NUMBER "29"
+#define CONTEXT_GROUP_KEYWORD "AcquisitionModality"
#define CONTEXT_GROUP_VERSION "20231115"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.19"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID29_AcquisitionModality::CID29_AcquisitionModality(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID29_AcquisitionModality::CID29_AcquisitionModality(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
Codes->insert(OFMake_pair(IntravascularOpticalCoherenceTomography, DSRBasicCodedEntry("IVOCT", "DCM", "Intravascular Optical Coherence Tomography")));
Codes->insert(OFMake_pair(IntravascularUltrasound, DSRBasicCodedEntry("IVUS", "DCM", "Intravascular Ultrasound")));
Codes->insert(OFMake_pair(Keratometry, DSRBasicCodedEntry("KER", "DCM", "Keratometry")));
- Codes->insert(OFMake_pair(LaserScan, DSRBasicCodedEntry("LS", "DCM", "Laser Scan")));
+ Codes->insert(OFMake_pair(LaserSurfaceScan, DSRBasicCodedEntry("LS", "DCM", "Laser surface scan")));
Codes->insert(OFMake_pair(Lensometry, DSRBasicCodedEntry("LEN", "DCM", "Lensometry")));
Codes->insert(OFMake_pair(MagneticResonance, DSRBasicCodedEntry("MR", "DCM", "Magnetic Resonance")));
Codes->insert(OFMake_pair(Mammography, DSRBasicCodedEntry("MG", "DCM", "Mammography")));
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID4020_PETRadionuclide
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:13 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:46 by J. Riesmeier
*
*/
// general information on CID 4020 (PET Radionuclide)
#define CONTEXT_GROUP_NUMBER "4020"
+#define CONTEXT_GROUP_KEYWORD "PETRadionuclide"
#define CONTEXT_GROUP_VERSION "20160119"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.304"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID4020_PETRadionuclide::CID4020_PETRadionuclide(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID4020_PETRadionuclide::CID4020_PETRadionuclide(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID4021_PETRadiopharmaceutical
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:14 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:47 by J. Riesmeier
*
*/
// general information on CID 4021 (PET Radiopharmaceutical)
#define CONTEXT_GROUP_NUMBER "4021"
-#define CONTEXT_GROUP_VERSION "20221201"
+#define CONTEXT_GROUP_KEYWORD "PETRadiopharmaceutical"
+#define CONTEXT_GROUP_VERSION "20251111"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.305"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID4021_PETRadiopharmaceutical::CID4021_PETRadiopharmaceutical(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID4021_PETRadiopharmaceutical::CID4021_PETRadiopharmaceutical(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/* and initialize it by adding the coded entries */
Codes->insert(OFMake_pair(_28H1_89Zr, DSRBasicCodedEntry("126752", "DCM", "28H1 ^89^Zr")));
Codes->insert(OFMake_pair(_2FA_F18, DSRBasicCodedEntry("126713", "DCM", "2FA F^18^")));
+ Codes->insert(OFMake_pair(_2Thymidine_C11, DSRBasicCodedEntry("C90936", "NCIt", "2-Thymidine C^11^")));
+ Codes->insert(OFMake_pair(_3NMethylspiperone_C11, DSRBasicCodedEntry("771875003", "SCT", "3-N-Methylspiperone C^11^")));
Codes->insert(OFMake_pair(_7D12_89Zr, DSRBasicCodedEntry("126751", "DCM", "7D12 ^89^Zr")));
Codes->insert(OFMake_pair(_7E11_89Zr, DSRBasicCodedEntry("126750", "DCM", "7E11 ^89^Zr")));
Codes->insert(OFMake_pair(Acetate_C11, DSRBasicCodedEntry("129513004", "SCT", "Acetate C^11^")));
Codes->insert(OFMake_pair(CLR1404_I131, DSRBasicCodedEntry("126716", "DCM", "CLR1404 I^131^")));
Codes->insert(OFMake_pair(CMAbU36_89Zr, DSRBasicCodedEntry("126746", "DCM", "cMAb U36 ^89^Zr")));
Codes->insert(OFMake_pair(CU36_89Zr, DSRBasicCodedEntry("126515", "DCM", "cU36 ^89^Zr")));
+ Codes->insert(OFMake_pair(DASB_C11, DSRBasicCodedEntry("C412822", "MSH", "DASB C^11^")));
Codes->insert(OFMake_pair(DCFBC_F18, DSRBasicCodedEntry("C96234", "NCIt", "DCFBC F^18^")));
- Codes->insert(OFMake_pair(Piflufolastat_F18, DSRBasicCodedEntry("C116352", "NCIt", "Piflufolastat F^18^")));
Codes->insert(OFMake_pair(DfFK2_89Zr, DSRBasicCodedEntry("126762", "DCM", "Df-[FK](2) ^89^Zr")));
Codes->insert(OFMake_pair(DfFK23PEG4_89Zr, DSRBasicCodedEntry("126763", "DCM", "Df-[FK](2)-3PEG(4) ^89^Zr")));
Codes->insert(OFMake_pair(DfCD45_89Zr, DSRBasicCodedEntry("126520", "DCM", "Df-CD45 ^89^Zr")));
Codes->insert(OFMake_pair(DfFK_89Zr, DSRBasicCodedEntry("126760", "DCM", "Df-FK ^89^Zr")));
Codes->insert(OFMake_pair(DfFKPEG3_89Zr, DSRBasicCodedEntry("126761", "DCM", "Df-FK-PEG(3) ^89^Zr")));
Codes->insert(OFMake_pair(DN30_89Zr, DSRBasicCodedEntry("126747", "DCM", "DN30 ^89^Zr")));
+ Codes->insert(OFMake_pair(Dotatate_Ga68, DSRBasicCodedEntry("724025002", "SCT", "Dotatate Ga^68^")));
Codes->insert(OFMake_pair(DPA713_11C, DSRBasicCodedEntry("126765", "DCM", "DPA-713 ^11^C")));
Codes->insert(OFMake_pair(DPA714_18F, DSRBasicCodedEntry("126766", "DCM", "DPA-714 ^18^F")));
Codes->insert(OFMake_pair(E4G10_89Zr, DSRBasicCodedEntry("126519", "DCM", "E4G10 ^89^Zr")));
Codes->insert(OFMake_pair(Flumazenil_C11, DSRBasicCodedEntry("423543007", "SCT", "Flumazenil C^11^")));
Codes->insert(OFMake_pair(Flumazenil_F18, DSRBasicCodedEntry("422975006", "SCT", "Flumazenil F^18^")));
Codes->insert(OFMake_pair(Fluorethyltyrosin_F18, DSRBasicCodedEntry("424708001", "SCT", "Fluorethyltyrosin F^18^")));
+ Codes->insert(OFMake_pair(FluoroazomycinArabinoside_F18, DSRBasicCodedEntry("C62520", "NCIt", "Fluoroazomycin arabinoside F^18^")));
Codes->insert(OFMake_pair(Fluorobenzothiazole_F18, DSRBasicCodedEntry("423546004", "SCT", "Fluorobenzothiazole F^18^")));
Codes->insert(OFMake_pair(Fluorocholine_F18, DSRBasicCodedEntry("456992002", "SCT", "Fluorocholine F^18^")));
Codes->insert(OFMake_pair(Fluorodeoxyglucose_F18, DSRBasicCodedEntry("35321007", "SCT", "Fluorodeoxyglucose F^18^")));
Codes->insert(OFMake_pair(Fluoromethane_F18, DSRBasicCodedEntry("422763008", "SCT", "Fluoromethane F^18^")));
Codes->insert(OFMake_pair(Fluoromisonidazole_F18, DSRBasicCodedEntry("422598008", "SCT", "Fluoromisonidazole F^18^")));
Codes->insert(OFMake_pair(FluoropropylDihydrotetrabenazine_F18, DSRBasicCodedEntry("C2934038", "UMLS", "Fluoropropyl-dihydrotetrabenazine F^18^")));
+ Codes->insert(OFMake_pair(Fluorothymidine_F18, DSRBasicCodedEntry("764937002", "SCT", "Fluorothymidine F^18^")));
Codes->insert(OFMake_pair(Fluorotriopride_F18, DSRBasicCodedEntry("126707", "DCM", "Fluorotriopride F^18^")));
Codes->insert(OFMake_pair(Fluorouracil_F18, DSRBasicCodedEntry("425236000", "SCT", "Fluorouracil F^18^")));
Codes->insert(OFMake_pair(Flurpiridaz_F18, DSRBasicCodedEntry("126718", "DCM", "Flurpiridaz F^18^")));
Codes->insert(OFMake_pair(GA201_89Zr, DSRBasicCodedEntry("126731", "DCM", "GA201 ^89^Zr")));
Codes->insert(OFMake_pair(Germanium_Ge68, DSRBasicCodedEntry("53315004", "SCT", "Germanium Ge^68^")));
Codes->insert(OFMake_pair(GlembatumumabVedotin_89Zr, DSRBasicCodedEntry("126724", "DCM", "Glembatumumab vedotin ^89^Zr")));
+ Codes->insert(OFMake_pair(Glucose_C11, DSRBasicCodedEntry("126521", "DCM", "Glucose C^11^")));
Codes->insert(OFMake_pair(Glutamate_N13, DSRBasicCodedEntry("129509006", "SCT", "Glutamate N^13^")));
Codes->insert(OFMake_pair(Glutamine_C11, DSRBasicCodedEntry("126709", "DCM", "Glutamine C^11^")));
Codes->insert(OFMake_pair(Glutamine_C14, DSRBasicCodedEntry("126710", "DCM", "Glutamine C^14^")));
Codes->insert(OFMake_pair(Palmitate_C11, DSRBasicCodedEntry("129514005", "SCT", "Palmitate C^11^")));
Codes->insert(OFMake_pair(Panitumumab_89Zr, DSRBasicCodedEntry("126736", "DCM", "Panitumumab ^89^Zr")));
Codes->insert(OFMake_pair(Pegdinetanib_89Zr, DSRBasicCodedEntry("126728", "DCM", "Pegdinetanib ^89^Zr")));
+ Codes->insert(OFMake_pair(Pembrolizumab_89Zr, DSRBasicCodedEntry("C148167", "NCIt", "Pembrolizumab ^89^Zr")));
+ Codes->insert(OFMake_pair(PI2620_F18, DSRBasicCodedEntry("C5433257", "UMLS", "PI-2620 F^18^")));
+ Codes->insert(OFMake_pair(Piflufolastat_F18, DSRBasicCodedEntry("C116352", "NCIt", "Piflufolastat F^18^")));
Codes->insert(OFMake_pair(PinatuzumabVedotin_89Zr, DSRBasicCodedEntry("126725", "DCM", "Pinatuzumab vedotin ^89^Zr")));
Codes->insert(OFMake_pair(PittsburghCompoundB_C11, DSRBasicCodedEntry("126500", "DCM", "Pittsburgh compound B C^11^")));
Codes->insert(OFMake_pair(PK11195_11C, DSRBasicCodedEntry("C1609883", "UMLS", "PK11195 ^11^C")));
Codes->insert(OFMake_pair(T807_F18, DSRBasicCodedEntry("126502", "DCM", "T807 F^18^")));
Codes->insert(OFMake_pair(THK5317_F18, DSRBasicCodedEntry("C4550127", "UMLS", "THK5317 F^18^")));
Codes->insert(OFMake_pair(THK5351_F18, DSRBasicCodedEntry("C4279748", "UMLS", "THK5351 F^18^")));
- Codes->insert(OFMake_pair(Thymidine_F18, DSRBasicCodedEntry("129502002", "SCT", "Thymidine F^18^")));
Codes->insert(OFMake_pair(Trastuzumab_89Zr, DSRBasicCodedEntry("126512", "DCM", "Trastuzumab ^89^Zr")));
Codes->insert(OFMake_pair(TRC105_89Zr, DSRBasicCodedEntry("126749", "DCM", "TRC105 ^89^Zr")));
- Codes->insert(OFMake_pair(Dotatate_Ga68, DSRBasicCodedEntry("724025002", "SCT", "Dotatate Ga^68^")));
Codes->insert(OFMake_pair(Ublituximab_89Zr, DSRBasicCodedEntry("126739", "DCM", "Ublituximab ^89^Zr")));
Codes->insert(OFMake_pair(UCBJ_C11, DSRBasicCodedEntry("C4506788", "UMLS", "UCB-J C^11^")));
Codes->insert(OFMake_pair(XmAb5574_89Zr, DSRBasicCodedEntry("126734", "DCM", "XmAb5574 ^89^Zr")));
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID4031_CommonAnatomicRegion
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:15 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:48 by J. Riesmeier
*
*/
// general information on CID 4031 (Common Anatomic Region)
#define CONTEXT_GROUP_NUMBER "4031"
-#define CONTEXT_GROUP_VERSION "20221224"
+#define CONTEXT_GROUP_KEYWORD "CommonAnatomicRegion"
+#define CONTEXT_GROUP_VERSION "20250709"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.308"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID4031_CommonAnatomicRegion::CID4031_CommonAnatomicRegion(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID4031_CommonAnatomicRegion::CID4031_CommonAnatomicRegion(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
Codes->insert(OFMake_pair(Breast, DSRBasicCodedEntry("76752008", "SCT", "Breast")));
Codes->insert(OFMake_pair(Bronchus, DSRBasicCodedEntry("955009", "SCT", "Bronchus")));
Codes->insert(OFMake_pair(Calcaneus, DSRBasicCodedEntry("80144004", "SCT", "Calcaneus")));
+ Codes->insert(OFMake_pair(CardiovascularSystem, DSRBasicCodedEntry("113257007", "SCT", "Cardiovascular system")));
Codes->insert(OFMake_pair(CervicalSpine, DSRBasicCodedEntry("122494005", "SCT", "Cervical spine")));
Codes->insert(OFMake_pair(CervicoThoracicSpine, DSRBasicCodedEntry("1217257000", "SCT", "Cervico-thoracic spine")));
Codes->insert(OFMake_pair(Chest, DSRBasicCodedEntry("816094009", "SCT", "Chest")));
- Codes->insert(OFMake_pair(ChestAndAbdomen, DSRBasicCodedEntry("416550000", "SCT", "Chest and Abdomen")));
Codes->insert(OFMake_pair(ChestAbdomenAndPelvis, DSRBasicCodedEntry("416775004", "SCT", "Chest, Abdomen and Pelvis")));
+ Codes->insert(OFMake_pair(ChestAndAbdomen, DSRBasicCodedEntry("416550000", "SCT", "Chest and Abdomen")));
Codes->insert(OFMake_pair(Clavicle, DSRBasicCodedEntry("51299004", "SCT", "Clavicle")));
Codes->insert(OFMake_pair(Coccyx, DSRBasicCodedEntry("64688005", "SCT", "Coccyx")));
Codes->insert(OFMake_pair(Colon, DSRBasicCodedEntry("71854001", "SCT", "Colon")));
Codes->insert(OFMake_pair(LiverAndBiliaryStructure, DSRBasicCodedEntry("303270005", "SCT", "Liver and biliary structure")));
Codes->insert(OFMake_pair(LowerLeg, DSRBasicCodedEntry("30021000", "SCT", "Lower leg")));
Codes->insert(OFMake_pair(LowerLimb, DSRBasicCodedEntry("61685007", "SCT", "Lower limb")));
+ Codes->insert(OFMake_pair(LowerTrunk, DSRBasicCodedEntry("63337009", "SCT", "Lower trunk")));
Codes->insert(OFMake_pair(LumbarSpine, DSRBasicCodedEntry("122496007", "SCT", "Lumbar spine")));
Codes->insert(OFMake_pair(LumboSacralSpine, DSRBasicCodedEntry("1217253001", "SCT", "Lumbo-sacral spine")));
Codes->insert(OFMake_pair(Mandible, DSRBasicCodedEntry("91609006", "SCT", "Mandible")));
Codes->insert(OFMake_pair(MuscleOfUpperLimb, DSRBasicCodedEntry("30608006", "SCT", "Muscle of upper limb")));
Codes->insert(OFMake_pair(NasalBone, DSRBasicCodedEntry("74386004", "SCT", "Nasal bone")));
Codes->insert(OFMake_pair(Neck, DSRBasicCodedEntry("45048000", "SCT", "Neck")));
- Codes->insert(OFMake_pair(NeckAndChest, DSRBasicCodedEntry("417437006", "SCT", "Neck and Chest")));
- Codes->insert(OFMake_pair(NeckChestAndAbdomen, DSRBasicCodedEntry("416152001", "SCT", "Neck, Chest and Abdomen")));
Codes->insert(OFMake_pair(NeckChestAbdomenAndPelvis, DSRBasicCodedEntry("416319003", "SCT", "Neck, Chest, Abdomen and Pelvis")));
+ Codes->insert(OFMake_pair(NeckChestAndAbdomen, DSRBasicCodedEntry("416152001", "SCT", "Neck, Chest and Abdomen")));
+ Codes->insert(OFMake_pair(NeckAndChest, DSRBasicCodedEntry("417437006", "SCT", "Neck and Chest")));
Codes->insert(OFMake_pair(OpticCanal, DSRBasicCodedEntry("55024004", "SCT", "Optic canal")));
Codes->insert(OFMake_pair(OrbitalStructure, DSRBasicCodedEntry("363654007", "SCT", "Orbital structure")));
Codes->insert(OFMake_pair(Pancreas, DSRBasicCodedEntry("15776009", "SCT", "Pancreas")));
Codes->insert(OFMake_pair(Skull, DSRBasicCodedEntry("89546000", "SCT", "Skull")));
Codes->insert(OFMake_pair(SmallIntestine, DSRBasicCodedEntry("30315005", "SCT", "Small intestine")));
Codes->insert(OFMake_pair(Spine, DSRBasicCodedEntry("421060004", "SCT", "Spine")));
+ Codes->insert(OFMake_pair(SpineAndPerOrCord, DSRBasicCodedEntry("737561001", "SCT", "Spine and/or cord")));
Codes->insert(OFMake_pair(SternoclavicularJoint, DSRBasicCodedEntry("7844006", "SCT", "Sternoclavicular joint")));
Codes->insert(OFMake_pair(Sternum, DSRBasicCodedEntry("56873002", "SCT", "Sternum")));
Codes->insert(OFMake_pair(Stomach, DSRBasicCodedEntry("69695003", "SCT", "Stomach")));
Codes->insert(OFMake_pair(Thumb, DSRBasicCodedEntry("76505004", "SCT", "Thumb")));
Codes->insert(OFMake_pair(Toe, DSRBasicCodedEntry("29707007", "SCT", "Toe")));
Codes->insert(OFMake_pair(Trachea, DSRBasicCodedEntry("44567001", "SCT", "Trachea")));
+ Codes->insert(OFMake_pair(Trunk, DSRBasicCodedEntry("22943007", "SCT", "Trunk")));
Codes->insert(OFMake_pair(UpperArm, DSRBasicCodedEntry("40983000", "SCT", "Upper arm")));
Codes->insert(OFMake_pair(UpperLimb, DSRBasicCodedEntry("53120007", "SCT", "Upper limb")));
+ Codes->insert(OFMake_pair(UpperTrunk, DSRBasicCodedEntry("67734004", "SCT", "Upper trunk")));
Codes->insert(OFMake_pair(UpperUrinaryTract, DSRBasicCodedEntry("431491007", "SCT", "Upper urinary tract")));
Codes->insert(OFMake_pair(Ureter, DSRBasicCodedEntry("87953007", "SCT", "Ureter")));
Codes->insert(OFMake_pair(Urethra, DSRBasicCodedEntry("13648007", "SCT", "Urethra")));
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID42_NumericValueQualifier
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:08 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:42 by J. Riesmeier
*
*/
// general information on CID 42 (Numeric Value Qualifier)
#define CONTEXT_GROUP_NUMBER "42"
+#define CONTEXT_GROUP_KEYWORD "NumericValueQualifier"
#define CONTEXT_GROUP_VERSION "20020114"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.22"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID42_NumericValueQualifier::CID42_NumericValueQualifier(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID42_NumericValueQualifier::CID42_NumericValueQualifier(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2022, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID5000_Language
// general information on CID 5000 (Language)
#define CONTEXT_GROUP_NUMBER "5000"
+#define CONTEXT_GROUP_KEYWORD "Language"
#define CONTEXT_GROUP_VERSION "" /* unknown */
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.328"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible? */
CID5000_Language::CID5000_Language(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID5000_Language::CID5000_Language(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2022, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID5001_Country
// general information on CID 5001 (Country)
#define CONTEXT_GROUP_NUMBER "5001"
+#define CONTEXT_GROUP_KEYWORD "Country"
#define CONTEXT_GROUP_VERSION "" /* unknown */
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.329"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible? */
CID5001_Country::CID5001_Country(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID5001_Country::CID5001_Country(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID6147_ResponseCriteria
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:16 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:49 by J. Riesmeier
*
*/
// general information on CID 6147 (Response Criteria)
#define CONTEXT_GROUP_NUMBER "6147"
+#define CONTEXT_GROUP_KEYWORD "ResponseCriteria"
#define CONTEXT_GROUP_VERSION "20141110"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.1004"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID6147_ResponseCriteria::CID6147_ResponseCriteria(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID6147_ResponseCriteria::CID6147_ResponseCriteria(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7021_MeasurementReportDocumentTitle
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:17 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:50 by J. Riesmeier
*
*/
// general information on CID 7021 (Measurement Report Document Title)
#define CONTEXT_GROUP_NUMBER "7021"
+#define CONTEXT_GROUP_KEYWORD "MeasurementReportDocumentTitle"
#define CONTEXT_GROUP_VERSION "20141110"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.997"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7021_MeasurementReportDocumentTitle::CID7021_MeasurementReportDocumentTitle(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7021_MeasurementReportDocumentTitle::CID7021_MeasurementReportDocumentTitle(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7181_AbstractMultiDimensionalImageModelComponentUnit
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:18 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:51 by J. Riesmeier
*
*/
// general information on CID 7181 (Abstract Multi-dimensional Image Model Component Unit)
#define CONTEXT_GROUP_NUMBER "7181"
+#define CONTEXT_GROUP_KEYWORD "AbstractMultiDimensionalImageModelComponentUnit"
#define CONTEXT_GROUP_VERSION "20180605"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.918"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7181_AbstractMultiDimensionalImageModelComponentUnit::CID7181_AbstractMultiDimensionalImageModelComponentUnit(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7181_AbstractMultiDimensionalImageModelComponentUnit::CID7181_AbstractMultiDimensionalImageModelComponentUnit(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7445_DeviceParticipatingRole
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:19 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:52 by J. Riesmeier
*
*/
// general information on CID 7445 (Device Participating Role)
#define CONTEXT_GROUP_NUMBER "7445"
+#define CONTEXT_GROUP_KEYWORD "DeviceParticipatingRole"
#define CONTEXT_GROUP_VERSION "20120406"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.1042"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7445_DeviceParticipatingRole::CID7445_DeviceParticipatingRole(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7445_DeviceParticipatingRole::CID7445_DeviceParticipatingRole(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7452_OrganizationalRole
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:20 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:52 by J. Riesmeier
*
*/
// general information on CID 7452 (Organizational Role)
#define CONTEXT_GROUP_NUMBER "7452"
+#define CONTEXT_GROUP_KEYWORD "OrganizationalRole"
#define CONTEXT_GROUP_VERSION "20170626"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.516"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7452_OrganizationalRole::CID7452_OrganizationalRole(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7452_OrganizationalRole::CID7452_OrganizationalRole(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7453_PerformingRole
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:21 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:53 by J. Riesmeier
*
*/
// general information on CID 7453 (Performing Role)
#define CONTEXT_GROUP_NUMBER "7453"
+#define CONTEXT_GROUP_KEYWORD "PerformingRole"
#define CONTEXT_GROUP_VERSION "20180326"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.517"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7453_PerformingRole::CID7453_PerformingRole(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7453_PerformingRole::CID7453_PerformingRole(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7464_GeneralRegionOfInterestMeasurementModifier
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:22 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:54 by J. Riesmeier
*
*/
// general information on CID 7464 (General Region of Interest Measurement Modifier)
#define CONTEXT_GROUP_NUMBER "7464"
+#define CONTEXT_GROUP_KEYWORD "GeneralRegionOfInterestMeasurementModifier"
#define CONTEXT_GROUP_VERSION "20121101"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.951"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7464_GeneralRegionOfInterestMeasurementModifier::CID7464_GeneralRegionOfInterestMeasurementModifier(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7464_GeneralRegionOfInterestMeasurementModifier::CID7464_GeneralRegionOfInterestMeasurementModifier(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7469_GenericIntensityAndSizeMeasurement
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:23 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:55 by J. Riesmeier
*
*/
// general information on CID 7469 (Generic Intensity and Size Measurement)
#define CONTEXT_GROUP_NUMBER "7469"
+#define CONTEXT_GROUP_KEYWORD "GenericIntensityAndSizeMeasurement"
#define CONTEXT_GROUP_VERSION "20240913"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.1003"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7469_GenericIntensityAndSizeMeasurement::CID7469_GenericIntensityAndSizeMeasurement(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7469_GenericIntensityAndSizeMeasurement::CID7469_GenericIntensityAndSizeMeasurement(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
/*
*
- * Copyright (C) 2015-2024, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* Source file for class CID7551_GenericPurposeOfReferenceToImagesAndCoordinatesInMeasurement
*
- * Generated automatically from DICOM PS 3.16-2024d
- * File created on 2024-10-08 10:25:24 by J. Riesmeier
+ * Generated automatically from DICOM PS 3.16-2025e
+ * File created on 2025-11-21 12:16:56 by J. Riesmeier
*
*/
// general information on CID 7551 (Generic Purpose of Reference to Images and Coordinates in Measurement)
#define CONTEXT_GROUP_NUMBER "7551"
+#define CONTEXT_GROUP_KEYWORD "GenericPurposeOfReferenceToImagesAndCoordinatesInMeasurement"
#define CONTEXT_GROUP_VERSION "20200920"
#define CONTEXT_GROUP_UID "1.2.840.10008.6.1.1343"
#define CONTEXT_GROUP_TYPE OFTrue /* extensible */
CID7551_GenericPurposeOfReferenceToImagesAndCoordinatesInMeasurement::CID7551_GenericPurposeOfReferenceToImagesAndCoordinatesInMeasurement(const DSRCodedEntryValue &selectedValue)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, selectedValue)
{
setExtensible(CONTEXT_GROUP_TYPE);
}
CID7551_GenericPurposeOfReferenceToImagesAndCoordinatesInMeasurement::CID7551_GenericPurposeOfReferenceToImagesAndCoordinatesInMeasurement(const EnumType selectedValue,
const OFBool enhancedEncodingMode)
- : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
+ : DSRContextGroup(CONTEXT_GROUP_NUMBER, "DCMR", CONTEXT_GROUP_KEYWORD, CONTEXT_GROUP_VERSION, CONTEXT_GROUP_UID, getCodedEntry(selectedValue, enhancedEncodingMode))
{
setExtensible(CONTEXT_GROUP_TYPE);
}
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmimgle/include/dcmtk/dcmimgle/dipixel.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimomod.h \
../../dcmimgle/include/dcmtk/dcmimgle/diluptab.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrobow.h \
../../dcmimgle/include/dcmtk/dcmimgle/dibaslut.h \
../../dcmimgle/include/dcmtk/dcmimgle/dimoopx.h \
../../dcmimgle/include/dcmtk/dcmimgle/didispfn.h \
../../ofstd/include/dcmtk/ofstd/ofcast.h \
../../ofstd/include/dcmtk/ofstd/ofexport.h \
../../ofstd/include/dcmtk/ofstd/oftypes.h \
- ../../ofstd/include/dcmtk/ofstd/ofstdinc.h
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h
dsrxmld.o: dsrxmld.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/dcmsr/dsrxmld.h ../include/dcmtk/dcmsr/dsrtypes.h \
../include/dcmtk/dcmsr/dsdefine.h \
/*
*
- * Copyright (C) 2015-2016, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
DSRContextGroup::DSRContextGroup(const OFString &contextIdentifier,
const OFString &mappingResource,
+ const OFString &contextGroupKeyword,
const OFString &contextGroupVersion,
const OFString &contextGroupUID,
const DSRCodedEntryValue &selectedValue)
: Identifier(contextIdentifier),
MappingResource(mappingResource),
+ Keyword(contextGroupKeyword),
Version(contextGroupVersion),
UID(contextGroupUID),
SelectedValue(selectedValue),
/* output some general information on the context group */
stream << "CID " << getIdentifier() << OFendl;
stream << " Resource : " << getMappingResource() << OFendl;
+ stream << " Keyword : " << getKeyword() << OFendl;
stream << " Version : " << getVersion() << OFendl;
stream << " UID : " << getUID() << OFendl;
stream << " Type : " << (isExtensible() ? "extensible" : "non-extensible") << OFendl;
/*
*
- * Copyright (C) 2000-2022, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
IssuerOfPatientID(DCM_IssuerOfPatientID),
PatientBirthDate(DCM_PatientBirthDate),
PatientSex(DCM_PatientSex),
+ PatientAge(DCM_PatientAge),
PatientSize(DCM_PatientSize),
PatientWeight(DCM_PatientWeight),
Manufacturer(DCM_Manufacturer),
IssuerOfPatientID.clear();
PatientBirthDate.clear();
PatientSex.clear();
+ PatientAge.clear();
PatientSize.clear();
PatientWeight.clear();
Manufacturer.clear();
VerificationFlagEnum = enumeratedValueToVerificationFlag(getStringValueFromElement(VerificationFlag, tmpString));
if (VerificationFlagEnum == VF_invalid)
printUnknownValueWarningMessage("VerificationFlag", tmpString.c_str());
+ else if ((VerificationFlagEnum == VF_Unverified) && !VerifyingObserver.isEmpty())
+ DCMSR_WARN("Verifying Observer(s) should not be present when Verification Flag is 'UNVERIFIED'");
else if (VerificationFlagEnum == VF_Verified)
checkElementValue(VerifyingObserver, "1-n", "1", obsSearchCond, "SRDocumentGeneralModule");
}
getAndCheckElementFromDataset(dataset, AccessionNumber, "1", "2", "GeneralStudyModule");
getAndCheckElementFromDataset(dataset, StudyDescription, "1", "3", "GeneralStudyModule");
// --- Patient Study Module ---
+ getAndCheckElementFromDataset(dataset, PatientAge, "1", "3", "PatientStudyModule");
getAndCheckElementFromDataset(dataset, PatientSize, "1", "3", "PatientStudyModule");
getAndCheckElementFromDataset(dataset, PatientWeight, "1", "3", "PatientStudyModule");
/* also read data from Patient Module */
addElementToDataset(result, dataset, new DcmCodeString(PatientSex), "1", "2", "PatientModule");
// --- Patient Study Module ---
+ addElementToDataset(result, dataset, new DcmAgeString(PatientAge), "1", "3", "PatientStudyModule");
addElementToDataset(result, dataset, new DcmDecimalString(PatientSize), "1", "3", "PatientStudyModule");
addElementToDataset(result, dataset, new DcmDecimalString(PatientWeight), "1", "3", "PatientStudyModule");
else if (doc.getElementFromNodeContent(cursor, PatientID, "id").bad() &&
doc.getElementFromNodeContent(cursor, IssuerOfPatientID, "issuer").bad() &&
doc.getElementFromNodeContent(cursor, PatientSex, "sex").bad() &&
- /* strictly speaking, Patient's Size and Weight belong to the Study IE */
+ /* strictly speaking, Patient's Age, Size and Weight belong to the Study IE */
+ doc.getElementFromNodeContent(cursor, PatientAge, "age").bad() &&
doc.getElementFromNodeContent(cursor, PatientSize, "size").bad() &&
doc.getElementFromNodeContent(cursor, PatientWeight, "weight").bad())
{
result = readXMLVerifyingObserverData(doc, cursor.getChild(), flags);
/* allow absence in case of UNVERIFIED */
if (VerificationFlagEnum == VF_Unverified)
+ {
+ if (!VerifyingObserver.isEmpty())
+ DCMSR_WARN("Verifying Observer(s) should not be present when Verification Flag is 'UNVERIFIED'");
result = EC_Normal;
+ }
} else
printUnknownValueWarningMessage("VerificationFlag", tmpString.c_str());
}
stream << "</birthday>" << OFendl;
}
writeStringFromElementToXML(stream, PatientSex, "sex", (flags & XF_writeEmptyTags) > 0);
- /* strictly speaking, Patient's Size and Weight belong to the Study IE */
+ /* strictly speaking, Patient's Age, Size and Weight belong to the Study IE */
+ writeStringFromElementToXML(stream, PatientAge, "age", (flags & XF_writeEmptyTags) > 0);
writeStringFromElementToXML(stream, PatientSize, "size", (flags & XF_writeEmptyTags) > 0);
writeStringFromElementToXML(stream, PatientWeight, "weight", (flags & XF_writeEmptyTags) > 0);
stream << "</patient>" << OFendl;
}
+OFCondition DSRDocument::getPatientAge(OFString &value,
+ const signed long pos) const
+{
+ return getStringValueFromElement(PatientAge, value, pos);
+}
+
+
OFCondition DSRDocument::getPatientSize(OFString &value,
const signed long pos) const
{
}
+OFCondition DSRDocument::setPatientAge(const OFString &value,
+ const OFBool check)
+{
+ OFCondition result = (check) ? DcmAgeString::checkStringValue(value, "1") : EC_Normal;
+ if (result.good())
+ result = PatientAge.putOFStringArray(value);
+ return result;
+}
+
+
OFCondition DSRDocument::setPatientSize(const OFString &value,
const OFBool check)
{
AccessionNumber.clear();
StudyDescription.clear();
/* also need to clear the attributes from the Patient Study Module */
+ PatientAge.clear();
PatientSize.clear();
PatientWeight.clear();
/* the following method also creates new a study (since UID is empty) and SOP instance */
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFBool DSRDocumentTreeNode::hasTemplateIdentification() const
{
- /* mapping resource UID is optional, so do not check it */
+ /* Mapping Resource UID is optional, so do not check it */
return !TemplateIdentifier.empty() && !MappingResource.empty();
}
DCMSR_WARN("Content item has invalid/incomplete template identification");
}
}
- /* read concept name (not required in some cases) */
+ /* read Concept Name (not required in some cases) */
ConceptName.readXML(doc, doc.getNamedChildNode(cursor, "concept", OFFalse /*required*/), flags);
- /* read observation UID and date/time (optional) */
+ /* read Observation UID and date/time (optional) */
const DSRXMLCursor childCursor = doc.getNamedChildNode(cursor, "observation", OFFalse /*required*/);
if (childCursor.valid())
{
}
}
}
- /* relationship type */
+ /* Relationship Type */
if ((RelationshipType != RT_isRoot) && !(flags & XF_relationshipTypeAsAttribute))
writeStringValueToXML(stream, relationshipTypeToDefinedTerm(RelationshipType), "relationship", (flags & XF_writeEmptyTags) > 0);
- /* concept name */
+ /* Concept Name */
if (ConceptName.isValid())
{
if (flags & XF_codeComponentsAsAttribute)
}
if (!(ObservationDateTime.empty() && ObservationUID.empty()))
{
- /* observation UID (optional) */
+ /* Observation UID (optional) */
OFString tmpString;
stream << "<observation";
if (!ObservationUID.empty())
const size_t flags)
{
OFCondition result = EC_Normal;
- /* read DocumentRelationshipMacro */
+ /* read Document Relationship Macro */
result = readDocumentRelationshipMacro(dataset, constraintChecker, "1" /*posString*/, flags);
- /* read DocumentContentMacro */
+ /* read Document Content Macro */
if (result.good())
result = readDocumentContentMacro(dataset, "1" /*posString*/, flags);
return result;
DcmStack *markedItems)
{
OFCondition result = EC_Normal;
- /* write DocumentRelationshipMacro */
+ /* write Document Relationship Macro */
result = writeDocumentRelationshipMacro(dataset, markedItems);
- /* write DocumentContentMacro */
+ /* write Document Content Macro */
if (result.good())
result = writeDocumentContentMacro(dataset);
return result;
getElementFromDataset(dataset, MACParameters);
getElementFromDataset(dataset, DigitalSignatures);
}
- /* read ObservationDateTime (conditional) */
+ /* read Observation DateTime (conditional) */
getAndCheckStringValueFromDataset(dataset, DCM_ObservationDateTime, ObservationDateTime, "1", "1C");
- /* read ObservationUID (optional) */
+ /* read Observation UID (optional) */
getAndCheckStringValueFromDataset(dataset, DCM_ObservationUID, ObservationUID, "1", "3");
/* determine template identifier expected for this document */
OFString expectedTemplateIdentifier;
OFString expectedMappingResource;
if (constraintChecker != NULL)
constraintChecker->getRootTemplateIdentification(expectedTemplateIdentifier, expectedMappingResource);
- /* read ContentTemplateSequence (conditional) */
+ /* read Content Template Sequence (conditional) */
DcmItem *ditem = NULL;
if (dataset.findAndGetSequenceItem(DCM_ContentTemplateSequence, ditem, 0 /*itemNum*/).good())
{
}
}
}
+ else if (!MappingResource.empty())
+ {
+ /* check whether an incorrect Mapping Resource UID is used */
+ if (MappingResourceUID == UID_DICOMContentMappingResource)
+ {
+ DCMSR_WARN("Incorrect value for Mapping Resource UID (" << MappingResourceUID << "), "
+ << "should only be used for 'DCMR' and not for '" << MappingResource << "'");
+ }
+ }
/* check whether the expected template (if known) has been used */
if (!expectedTemplateIdentifier.empty())
{
DCMSR_WARN("Content Template Sequence missing or empty, Template Identifier "
<< expectedTemplateIdentifier << " (" << expectedMappingResource << ") expected");
}
- /* read ContentSequence */
+ /* read Content Sequence */
if (result.good())
result = readContentSequence(dataset, constraintChecker, posString, flags);
return result;
/* add to marked items stack */
if (MarkFlag && (markedItems != NULL))
markedItems->push(&dataset);
- /* write ObservationDateTime (conditional) */
+ /* write Observation DateTime (conditional) */
result = putStringValueToDataset(dataset, DCM_ObservationDateTime, ObservationDateTime, OFFalse /*allowEmpty*/);
- /* write ObservationUID (optional) */
+ /* write Observation UID (optional) */
if (result.good())
result = putStringValueToDataset(dataset, DCM_ObservationUID, ObservationUID, OFFalse /*allowEmpty*/);
- /* write ContentTemplateSequence (conditional) */
+ /* write Content Template Sequence (conditional) */
if (result.good())
{
if (hasTemplateIdentification())
const size_t flags)
{
OFCondition result = EC_Normal;
- /* skip reading ValueType, already done somewhere else */
+ /* skip reading Value Type, already done somewhere else */
- /* read ConceptNameCodeSequence */
+ /* read Concept Name Code Sequence */
if (RelationshipType == RT_isRoot)
{
/* the concept name is required for the root container */
{
if (result.bad())
DCMSR_DEBUG("Ignoring content item error because of read flag");
- /* read ContentItem (depending on ValueType) */
+ /* read Content Item (depending on Value Type) */
result = readContentItem(dataset, flags);
}
/* check for validity, after reading */
OFCondition DSRDocumentTreeNode::writeDocumentContentMacro(DcmItem &dataset) const
{
OFCondition result = EC_Normal;
- /* write ValueType */
+ /* write Value Type */
result = putStringValueToDataset(dataset, DCM_ValueType, valueTypeToDefinedTerm(ValueType));
- /* write ConceptNameCodeSequence */
+ /* write Concept Name Code Sequence */
if (result.good())
{
if (ConceptName.isValid())
/* check for validity, before writing */
if (!isValid())
printInvalidContentItemMessage("Writing", this);
- /* write ContentItem (depending on ValueType) */
+ /* write Content Item (depending on Value Type) */
result = writeContentItem(dataset);
}
return result;
{
OFCondition result = EC_Normal;
DcmSequenceOfItems *dseq = NULL;
- /* read ContentSequence (might be absent or empty) */
+ /* read Content Sequence (might be absent or empty) */
if (dataset.findAndGetSequence(DCM_ContentSequence, dseq).good())
{
OFString tmpString;
location += numberToString(OFstatic_cast(size_t, i + 1), buffer, sizeof(buffer));
if (flags & RF_showCurrentlyProcessedItem)
DCMSR_INFO("Processing content item " << location);
- /* read RelationshipType */
+ /* read Relationship Type */
result = getAndCheckStringValueFromDataset(*ditem, DCM_RelationshipType, tmpString, "1", "1", "content item");
if (result.good() || (flags & RF_acceptUnknownRelationshipType))
{
{
/* create new node (by-reference, no constraint checker required) */
result = createAndAppendNewNode(node, relationshipType, VT_byReference);
- /* read ReferencedContentItemIdentifier (again) */
+ /* read Referenced Content Item Identifier (again) */
if (result.good())
{
newNode = node;
result = node->readContentItem(*ditem, flags);
}
} else {
- /* read ValueType (from DocumentContentMacro) - required to create new node */
+ /* read Value Type (from Document Content Macro) - required to create new node */
result = getAndCheckStringValueFromDataset(*ditem, DCM_ValueType, tmpString, "1", "1", "content item");
if (result.good())
{
{
/* create new node (by-value) */
result = createAndAppendNewNode(node, relationshipType, valueType, (flags & RF_ignoreRelationshipConstraints) ? NULL : constraintChecker);
- /* read RelationshipMacro */
+ /* read Relationship Macro */
if (result.good())
{
newNode = node;
result = node->readDocumentRelationshipMacro(*ditem, constraintChecker, location, flags);
- /* read DocumentContentMacro */
+ /* read Document Content Macro */
if (result.good())
result = node->readDocumentContentMacro(*ditem, location.c_str(), flags);
} else {
DSRDocumentTreeNodeCursor cursor(getDown());
if (cursor.isValid())
{
- /* write ContentSequence */
+ /* write Content Sequence */
DcmSequenceOfItems *dseq = new DcmSequenceOfItems(DCM_ContentSequence);
if (dseq != NULL)
{
ditem = new DcmItem();
if (ditem != NULL)
{
- /* write RelationshipType */
+ /* write Relationship Type */
result = putStringValueToDataset(*ditem, DCM_RelationshipType, relationshipTypeToDefinedTerm(node->getRelationshipType()));
/* check for by-reference relationship */
if (node->getValueType() == VT_byReference)
{
- /* write ReferencedContentItemIdentifier */
+ /* write Referenced Content Item Identifier */
if (result.good())
result = node->writeContentItem(*ditem);
} else { // by-value
- /* write RelationshipMacro */
+ /* write Relationship Macro */
if (result.good())
result = node->writeDocumentRelationshipMacro(*ditem, markedItems);
- /* write DocumentContentMacro */
+ /* write Document Content Macro */
if (result.good())
node->writeDocumentContentMacro(*ditem);
}
if (!ConceptName.getCodeMeaning().empty())
{
docStream << "<b>";
- /* render ConceptName & Code (if valid) */
+ /* render Concept Name & Code (if valid) */
ConceptName.renderHTML(docStream, flags, (flags & HF_renderConceptNameCodes) && ConceptName.isValid() /*fullCode*/);
docStream << ":</b>";
writeLine = OFTrue;
else if (flags & HF_currentlyInsideAnnex)
{
docStream << "<b>";
- /* render ValueType only */
+ /* render Value Type only */
docStream << valueTypeToReadableName(ValueType);
docStream << ":</b>";
writeLine = OFTrue;
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
/* do not check values since this would be unexpected to the user */
- /* create copy of icon image (if any), first frame only */
- if (referenceValue.IconImage != NULL)
- IconImage = referenceValue.IconImage->createDicomImage(0 /*fstart*/, 1 /*fcount*/);
+ /* create copy of icon image (if any) */
+ copyIconImage(referenceValue.IconImage);
}
SegmentList = referenceValue.SegmentList;
PresentationState = referenceValue.PresentationState;
RealWorldValueMapping = referenceValue.RealWorldValueMapping;
- /* create copy of icon image (if any), first frame only */
- IconImage = (referenceValue.IconImage != NULL) ? referenceValue.IconImage->createDicomImage(0 /*fstart*/, 1 /*fcount*/) : NULL;
+ /* create copy of icon image (if any) */
+ copyIconImage(referenceValue.IconImage);
}
return *this;
}
}
+OFBool DSRImageReferenceValue::hasIconImage() const
+{
+ return (IconImage != NULL);
+}
+
+
OFCondition DSRImageReferenceValue::print(STD_NAMESPACE ostream &stream,
const size_t flags) const
{
/* ignore status (return value) since the references are optional */
setPresentationState(referenceValue.PresentationState, check);
setRealWorldValueMapping(referenceValue.RealWorldValueMapping, check);
+ /* create copy of icon image (if any) */
+ copyIconImage(referenceValue.IconImage);
}
return result;
}
}
+void DSRImageReferenceValue::copyIconImage(DicomImage *image)
+{
+ /* first, delete the current icon image */
+ delete IconImage;
+ /* then create a copy of the given icon image (first frame only) */
+ if (image != NULL)
+ IconImage = image->createDicomImage(0 /*fstart*/, 1 /*fcount*/);
+ else
+ IconImage = NULL;
+}
+
+
// comparison operators
OFBool operator==(const DSRImageReferenceValue &lhs,
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
stream << "<float>";
if (hasFloating)
{
- /* increase default precision */
- const STD_NAMESPACE streamsize oldPrecision = stream.precision(8);
- stream << floatValue;
- /* reset i/o manipulators */
- stream.precision(oldPrecision);
+ char buffer[64];
+ /* need to convert float to avoid problems with decimal point and "-nan" */
+ OFStandard::ftoa(buffer, sizeof(buffer), floatValue, 0, 0, -2 /* print enough digits to permit lossless conversion back to FD */);
+ stream << buffer;
}
stream << "</float>" << OFendl;
}
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{DSRTypes::PT_VolumeRendering, UID_VolumeRenderingVolumetricPresentationStateStorage, "VR-VPS"},
{DSRTypes::PT_SegmentedVolumeRendering, UID_SegmentedVolumeRenderingVolumetricPresentationStateStorage, "SVR-VPS"},
{DSRTypes::PT_MultipleVolumeRendering, UID_MultipleVolumeRenderingVolumetricPresentationStateStorage, "MVR-VPS"},
- {DSRTypes::PT_VariableModalityLUT, UID_VariableModalityLUTSoftcopyPresentationStateStorage, "VML-SPS"}
+ {DSRTypes::PT_VariableModalityLUT, UID_VariableModalityLUTSoftcopyPresentationStateStorage, "VML-SPS"},
+ {DSRTypes::PT_Waveform, UID_WaveformPresentationStateStorage, "WPS"},
+ {DSRTypes::PT_WaveformAcquisition, UID_WaveformAcquisitionPresentationStateStorage, "WAPS"}
};
/*
*
- * Copyright (C) 2003-2024, OFFIS e.V.
+ * Copyright (C) 2003-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#endif /* LIBXML_SCHEMAS_ENABLED */
// This function is also used in xml2dcm, try to stay in sync!
-#if defined(HAVE_VSNPRINTF) && defined(HAVE_PROTOTYPE_VSNPRINTF)
extern "C" void errorFunction(void * ctx, const char *msg, ...)
-#else
-extern "C" void errorFunction(void * /* ctx */, const char *msg, ...)
-#endif
{
OFLogger xmlLogger = OFLog::getLogger("dcmtk.dcmsr.libxml");
if (!xmlLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
return;
-#if defined(HAVE_VSNPRINTF) && defined(HAVE_PROTOTYPE_VSNPRINTF)
// libxml calls us multiple times for one line of log output which would
// result in garbled output. To avoid this, we buffer the output in a local
// string in the caller which we get through our 'ctx' parameter. Then, we
pos = buffer.find('\n');
}
-#else
- // No vsnprint, but at least vfprintf. Output the messages directly to stderr.
- va_list ap;
- va_start(ap, msg);
-#ifdef HAVE_PROTOTYPE_STD__VFPRINTF
- std::vfprintf(stderr, msg, ap);
-#else
- vfprintf(stderr, msg, ap);
-#endif
- va_end(ap);
-#endif
-
-#ifndef HAVE_VSNPRINTF
- // Only the vsnprintf() branch above uses 'buffer' which means the compiler
- // would warn about an unused variable if HAVE_VSNPRINTF is undefined.
- buffer += "";
-#endif
}
#endif /* WITH_LIBXML */
tsrdoc.cc
tsrdoctr.cc
tsrlist.cc
+ tsrimgvl.cc
tsrnumvl.cc
tsrtpl.cc
tsrtree.cc
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../../dcmdata/include/dcmtk/dcmdata/dcpixseq.h \
../../dcmdata/include/dcmtk/dcmdata/dcofsetl.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrae.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrur.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
../include/dcmtk/dcmsr/dsrreftn.h ../include/dcmtk/dcmsr/dsrimgtn.h \
../include/dcmtk/dcmsr/dsrnumtn.h ../include/dcmtk/dcmsr/dsrtextn.h \
../include/dcmtk/dcmsr/dsrstrvl.h
+tsrimgvl.o: tsrimgvl.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../include/dcmtk/dcmsr/dsrimgvl.h ../include/dcmtk/dcmsr/dsrtypes.h \
+ ../include/dcmtk/dcmsr/dsdefine.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../include/dcmtk/dcmsr/dsrcomvl.h ../include/dcmtk/dcmsr/dsrimgfr.h \
+ ../include/dcmtk/dcmsr/dsrtlist.h ../include/dcmtk/dcmsr/dsrimgse.h \
+ ../include/dcmtk/dcmsr/dsrimgtn.h ../include/dcmtk/dcmsr/dsrdoctn.h \
+ ../include/dcmtk/dcmsr/dsrtree.h ../include/dcmtk/dcmsr/dsrtncsr.h \
+ ../include/dcmtk/dcmsr/dsrposcn.h ../include/dcmtk/dcmsr/dsrtnant.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstack.h \
+ ../include/dcmtk/dcmsr/dsrcodvl.h ../include/dcmtk/dcmsr/codes/dcm.h
tsrlist.o: tsrlist.cc ../../config/include/dcmtk/config/osconfig.h \
../../ofstd/include/dcmtk/ofstd/oftest.h \
../../ofstd/include/dcmtk/ofstd/ofconapp.h \
../include/dcmtk/dcmsr/dsrwavch.h ../include/dcmtk/dcmsr/dsrrtpl.h \
../include/dcmtk/dcmsr/dsrctpl.h ../include/dcmtk/dcmsr/dsrsoprf.h \
../include/dcmtk/dcmsr/dsrrefin.h ../include/dcmtk/dcmsr/dsrcsidl.h \
- ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvras.h \
../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrda.h \
../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
LOCALLIBS = -lcmr -ldcmsr -ldcmimage -ldcmimgle -ldcmdata -loflog -lofstd -loficonv \
$(TIFFLIBS) $(PNGLIBS) $(XMLLIBS) $(ZLIBLIBS) $(CHARCONVLIBS) $(MATHLIBS)
-tstobjs = tests.o tsrtree.o tsrdoctr.o tsrdoc.o tsrcodvl.o tsrnumvl.o tsrtpl.o \
- tsrcmr.o tsrlist.o
+tstobjs = tests.o tsrtree.o tsrdoctr.o tsrdoc.o tsrcodvl.o tsrimgvl.o tsrnumvl.o \
+ tsrtpl.o tsrcmr.o tsrlist.o
objs = mkreport.o $(tstobjs)
progs = mkreport tests
/*
*
- * Copyright (C) 2012-2022, OFFIS e.V.
+ * Copyright (C) 2012-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFTEST_REGISTER(dcmsr_writeCodeSequence);
OFTEST_REGISTER(dcmsr_compareCodedEntry);
OFTEST_REGISTER(dcmsr_useBasicCodedEntry);
+OFTEST_REGISTER(dcmsr_createMonochromeIconImage);
+OFTEST_REGISTER(dcmsr_createColorIconImage);
OFTEST_REGISTER(dcmsr_setNumericMeasurementValue);
OFTEST_REGISTER(dcmsr_emptyMeasurementValueSequence);
OFTEST_REGISTER(dcmsr_setAndGetFloatingPointRepresentation);
/*
*
- * Copyright (C) 2015-2022, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2015-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
OFCHECK(ctxGroup.mapModality("XYZ").isEmpty());
OFCHECK(ctxGroup.mapModality("ABC", codedEntry) == SR_EC_UnsupportedValue);
OFCHECK(ctxGroup.selectValue("").bad());
+ /* also check the keyword of the context group */
+ OFCHECK_EQUAL(ctxGroup.getKeyword(), "AcquisitionModality");
}
OFCHECK(ctxGroup.findCodedEntry(DSRBasicCodedEntry("", "99TEST", "Some invalid test code")).bad());
OFCHECK(ctxGroup.findCodedEntry(DSRBasicCodedEntry("0815", "99TEST", "-")).good());
OFCHECK(ctxGroup.findCodedEntry(DSRBasicCodedEntry("", "", "")).bad());
+ /* also check the keyword of the context group */
+ OFCHECK_EQUAL(ctxGroup.getKeyword(), "NumericValueQualifier");
}
OFCHECK(!ctxGroup.mapImageLaterality("XYZ").isValid());
OFCHECK(ctxGroup.mapImageLaterality("ABC", codedEntry) == SR_EC_InvalidValue);
OFCHECK(ctxGroup.selectValue("").bad());
+ /* also check the keyword of the context group */
+ OFCHECK_EQUAL(ctxGroup.getKeyword(), "Laterality");
}
/*
*
- * Copyright (C) 2014-2021, J. Riesmeier, Oldenburg, Germany
+ * Copyright (C) 2014-2025, J. Riesmeier, Oldenburg, Germany
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
OFCHECK(doc.getPatientSex(value).good());
OFCHECK_EQUAL(value, "M");
/* also check some recently introduced attributes */
+ OFCHECK(doc.setPatientAge("042Y").good());
+ OFCHECK(doc.getPatientAge(value).good());
+ OFCHECK_EQUAL(value, "042Y");
OFCHECK(doc.setPatientSize("1.88").good());
OFCHECK(doc.getPatientSize(value).good());
OFCHECK_EQUAL(value, "1.88");
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, J. Riesmeier, Oldenburg, Germany
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation are maintained by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmsr
+ *
+ * Author: Joerg Riesmeier
+ *
+ * Purpose:
+ * test program for class DSRImageReferenceValue
+ *
+ */
+
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/ofstd/oftest.h"
+
+#include "dcmtk/dcmdata/dcuid.h"
+#include "dcmtk/dcmdata/dcdatset.h"
+#include "dcmtk/dcmdata/dcdeftag.h"
+#include "dcmtk/dcmdata/dctypes.h"
+
+#include "dcmtk/dcmsr/dsrimgvl.h"
+#include "dcmtk/dcmsr/dsrimgtn.h"
+#include "dcmtk/dcmsr/codes/dcm.h"
+
+
+OFTEST(dcmsr_createMonochromeIconImage)
+{
+ DSRImageReferenceValue imgValue(UID_CTImageStorage, "1.2.3.4.5.6.7.8.9.0.98");
+ OFCHECK(!imgValue.hasIconImage());
+
+ /* create a monochrome image dataset */
+ DcmDataset dataset;
+ Uint8 pixelData[256];
+ for (int i = 0; i < 256; i++)
+ pixelData[i] = OFstatic_cast(Uint8, i);
+ OFCHECK(dataset.putAndInsertString(DCM_PhotometricInterpretation, "MONOCHROME2").good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_SamplesPerPixel, 1).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_PixelRepresentation, 0).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_Rows, 16).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_Columns, 16).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_BitsAllocated, 8).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_BitsStored, 8).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_HighBit, 7).good());
+ OFCHECK(dataset.putAndInsertUint8Array(DCM_PixelData, pixelData, sizeof(pixelData)).good());
+
+ /* create an icon image with 64x64 pixels */
+ OFCHECK(imgValue.createIconImage(&dataset, EXS_Unknown /*xfer*/, 0 /*frame*/, 64 /*width*/, 64 /*height*/).good());
+ OFCHECK(imgValue.hasIconImage());
+
+ /* set value to image tree node and write to item */
+ DcmItem item;
+ DSRImageTreeNode imgNode(DSRTypes::RT_contains);
+ OFCHECK(imgNode.setConceptName(CODE_DCM_BestInSet).good());
+ OFCHECK(imgNode.setValue(imgValue).good());
+ OFCHECK(imgNode.hasIconImage());
+ OFCHECK(imgNode.write(item).good());
+ /* output content of the item (in debug mode only) */
+ if (DCM_dcmsrLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
+ item.print(COUT, DCMTypes::PF_shortenLongTagValues /*flags*/, 2 /*level*/);
+
+ /* delete the icon image */
+ imgNode.deleteIconImage();
+ OFCHECK(!imgNode.hasIconImage());
+}
+
+
+OFTEST(dcmsr_createColorIconImage)
+{
+ DSRImageReferenceValue imgValue(UID_CTImageStorage, "1.2.3.4.5.6.7.8.9.0.99");
+ OFCHECK(!imgValue.hasIconImage());
+
+ /* create a color image dataset */
+ DcmDataset dataset;
+ Uint8 pixelData[256][3];
+ for (int i = 0; i < 256; i++)
+ {
+ pixelData[i][0] = OFstatic_cast(Uint8, i);
+ pixelData[i][1] = OFstatic_cast(Uint8, i);
+ pixelData[i][2] = OFstatic_cast(Uint8, i);
+ }
+ OFCHECK(dataset.putAndInsertString(DCM_PhotometricInterpretation, "RGB").good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_SamplesPerPixel, 3).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_PixelRepresentation, 0).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_PlanarConfiguration, 0).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_Rows, 16).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_Columns, 16).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_BitsAllocated, 8).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_BitsStored, 8).good());
+ OFCHECK(dataset.putAndInsertUint16(DCM_HighBit, 7).good());
+ OFCHECK(dataset.putAndInsertUint8Array(DCM_PixelData, pixelData[0], sizeof(pixelData)).good());
+
+ /* create an icon image with 64x64 pixels */
+ OFCHECK(imgValue.createIconImage(&dataset, EXS_Unknown /*xfer*/, 0 /*frame*/, 64 /*width*/, 64 /*height*/).good());
+ OFCHECK(imgValue.hasIconImage());
+
+ /* set value to image tree node and write to item */
+ DcmItem item;
+ DSRImageTreeNode imgNode(DSRTypes::RT_hasProperties);
+ OFCHECK(imgNode.setConceptName(CODE_DCM_BestIllustrationOfFinding).good());
+ OFCHECK(imgNode.setValue(imgValue).good());
+ OFCHECK(imgNode.hasIconImage());
+ OFCHECK(imgNode.write(item).good());
+ /* output content of the item (in debug mode only) */
+ if (DCM_dcmsrLogger.isEnabledFor(OFLogger::DEBUG_LOG_LEVEL))
+ item.print(COUT, DCMTypes::PF_shortenLongTagValues /*flags*/, 2 /*level*/);
+
+ /* delete the icon image */
+ imgNode.deleteIconImage();
+ OFCHECK(!imgNode.hasIconImage());
+}
/*
*
- * Copyright (C) 2010-2023, OFFIS e.V.
+ * Copyright (C) 2010-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
*/
virtual OFCondition setTLSProfile(DcmTLSSecurityProfile profile);
+ /** activate the ciphersuites that have been added to the list of ciphersuites
+ * for TLS negotiation. Caller must ensure that initNetwork() is executed before this call.
+ * @return EC_Normal if successful, an error code otherwise
+ */
+ virtual OFCondition activateCipherSuites();
+
/** adds a ciphersuite to the list of ciphersuites for TLS negotiation.
* Caller must ensure that initNetwork() is executed before this call.
* It is the responsibility of the user to ensure that the added ciphersuite
/*
*
- * Copyright (C) 2018-2024, OFFIS e.V.
+ * Copyright (C) 2018-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{"TLS_AES_256_GCM_SHA384", TLS1_3_RFC_AES_256_GCM_SHA384, TPV_TLSv13, TKE_TLSv13, TCA_TLSv13, TCE_AES, TCM_SHA384, TKM_GCM, 256, 256},
};
-#define GLOBAL_NUM_TLS13_CIPHERSUITES (sizeof(globalCipherSuiteList)/sizeof(DcmCipherSuiteList))
+#define GLOBAL_NUM_TLS13_CIPHERSUITES (sizeof(globalTLS13CipherSuiteList)/sizeof(DcmCipherSuiteList))
const size_t DcmTLSCiphersuiteHandler::unknownCipherSuiteIndex = (size_t) -1;
/*
*
- * Copyright (C) 2018-2024, OFFIS e.V.
+ * Copyright (C) 2018-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include <openssl/tls1.h>
END_EXTERN_C
-/* check if we fulfil all requirements for implementing the
+/* check if we fulfil all requirements for implementing the
* Modified BCP 195 RFC 8996 TLS Profile. With DICOM CP 2311
* making support for Camellia in GCM mode optional, this is now rather simple.
*/
/*
*
- * Copyright (C) 2010-2023, OFFIS e.V.
+ * Copyright (C) 2010-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
} else return EC_IllegalCall;
}
+OFCondition DcmTLSSCU::activateCipherSuites()
+{
+ if (m_tLayer)
+ {
+ return m_tLayer->activateCipherSuites();
+ }
+ return EC_IllegalCall;
+}
+
void DcmTLSSCU::setReadSeedFile(const OFString& seedFile)
{
m_readSeedFile = seedFile;
/*
*
- * Copyright (C) 1998-2024, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
DCMTK_ADD_TEST_EXECUTABLE(dcmtls_tests tests.cc tscuscptls.cc)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(dcmtls_tests dcmnet dcmtls)
+DCMTK_TARGET_LINK_MODULES(dcmtls_tests dcmtls)
# This macro parses tests.cc and registers all tests
DCMTK_ADD_TESTS(dcmtls)
/*
*
- * Copyright (C) 2019-2023, OFFIS e.V.
+ * Copyright (C) 2019-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
return; \
} while (0)
-/** Method that ensures that the current thread is actually sleeping for the
- * defined number of seconds (at least).
- * The problem with the regular sleep() function called from OFStandard::sleep
- * is that it might be interrupted by signals or a network timeout (depending
- * on the operating system). This methods re-executes OFStandard's sleep method
- * until the desired number of seconds have elapsed.
- * @param sleep The number of seconds to sleep (at least)
- */
-static void force_sleep(Uint32 sleep)
-{
- OFTimer timer;
- double elapsed = timer.getDiff();
- while (elapsed < (double)sleep)
- {
- // Use ceiling since otherwise we could wait too short
- OFStandard::sleep(OFstatic_cast(unsigned int, ceil(sleep-elapsed)));
- elapsed = timer.getDiff();
- }
-}
-
+const size_t NUM_THREADS = 20;
/** TestSCP derived from DcmSCP in order to test TLS functionality
* through function setTransportLayer of DcmSCPConfig.
m_is_running = OFTrue;
m_listen_result = listen();
m_is_running = OFFalse;
+ DCMNET_DEBUG("TestPool: SCP Pool thread stopped, listen() returned: " << m_listen_result.text());
}
};
port_number = 0xF000 + (rnd.getRND16() & 0xFFF);
config.setPort(port_number);
scp.start();
- force_sleep(2); // wait 2 seconds for the SCP process to start
+ OFStandard::forceSleep(2); // wait 2 seconds for the SCP process to start
memory_barrier.lock();
memory_barrier.unlock();
}
xfers.push_back(UID_LittleEndianImplicitTransferSyntax);
OFCHECK(config.addPresentationContext(UID_VerificationSOPClass, xfers, ASC_SC_ROLE_DEFAULT).good());
config.setTransportLayer(&scpTlsLayer);
- pool.setMaxThreads(20);
+ pool.setMaxThreads(NUM_THREADS);
// Ensure server is up and listening
int i = 0;
Uint16 port_number = 0;
- OFMutex memory_barrier;
do
{
// generate a random port number between 61440 (0xF000) and 65535
port_number = 0xF000 + (rnd.getRND16() & 0xFFF);
config.setPort(port_number);
pool.start();
- force_sleep(2); // wait 2 seconds for the SCP process to start
- memory_barrier.lock();
- memory_barrier.unlock();
+ OFStandard::forceSleep(2); // wait 2 seconds for the SCP process to start
}
while ((i++ < 5) && (! pool.m_is_running)); // try up to 5 port numbers before giving up
- if (! pool.m_is_running) BAILOUT("Start of the SCP thread ppol failed: " << pool.m_listen_result.text());
+ if (! pool.m_is_running) BAILOUT("Start of the SCP thread pool failed: " << pool.m_listen_result.text());
- OFVector<TestTLSSCU*> scus(20);
+ OFVector<TestTLSSCU*> scus(NUM_THREADS);
OFVector<DcmTLSTransportLayer*> scuTlsLayers;
for (OFVector<TestTLSSCU*>::iterator it1 = scus.begin(); it1 != scus.end(); ++it1)
{
// "ensure" the pool is initialized before any SCU starts connecting to it. The initialization
// can take a couple of seconds on older systems, e.g. debian i368.
- force_sleep(5);
+ OFStandard::forceSleep(5);
for (OFVector<TestTLSSCU*>::const_iterator it2 = scus.begin(); it2 != scus.end(); ++it2)
{
include_directories("${dcmtract_SOURCE_DIR}/include" "${dcmiod_SOURCE_DIR}/include" "${dcmdata_SOURCE_DIR}/include" "${ofstd_SOURCE_DIR}/include" "${oflog_SOURCE_DIR}/include" ${ZLIB_INCDIR})
# recurse into subdirectories
-foreach(SUBDIR libsrc include)
+foreach(SUBDIR libsrc include tests)
add_subdirectory(${SUBDIR})
endforeach()
/*
*
- * Copyright (C) 2016-2022, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
* (must be either 0, 1 or numPoints)
* @param result Returns the resulting Track if creation was successful,
* error otherwise
+ * @return EC_Normal if successful, error code otherwise
*/
virtual OFCondition addTrack(const Float32* pointData,
const size_t numPoints,
/*
*
- * Copyright (C) 2016-2024, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
extern DCMTK_DCMTRACT_EXPORT const OFConditionConst TRC_EC_InvalidStatisticData;
/// Invalid Track Data
extern DCMTK_DCMTRACT_EXPORT const OFConditionConst TRC_EC_InvalidTrackData;
+/// Invalid Content Identification
+extern DCMTK_DCMTRACT_EXPORT const OFConditionConst TRC_EC_InvalidContentIdentification;
/**
* Types specific to this module
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../include/dcmtk/dcmtract/trctypes.h ../include/dcmtk/dcmtract/trcdef.h \
../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
../../ofstd/include/dcmtk/ofstd/ofmap.h \
../../ofstd/include/dcmtk/ofstd/ofdate.h \
../../ofstd/include/dcmtk/ofstd/oftime.h \
/*
*
- * Copyright (C) 2016-2024, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
m_Rules->addRule(new IODRule(DCM_ContentTime, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
m_Rules->addRule(new IODRule(DCM_ContentDate, "1", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
m_Rules->addRule(new IODRule(DCM_TrackSetSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
- m_Rules->addRule(new IODRule(DCM_ReferencedInstanceSequence, "1-n", "1", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
+ m_Rules->addRule(new IODRule(DCM_ReferencedInstanceSequence, "1-n", "1C", getName(), DcmIODTypes::IE_INSTANCE), OFTrue);
}
OFCondition TrcTractographyResultsModule::check(const OFBool quiet)
{
+ DCMTRACT_DEBUG("Checking Tractography Results Module");
+ DCMTRACT_DEBUG("Checking Content Identification");
if (m_ContentIdentification.check().good())
{
+ DCMTRACT_DEBUG("Content Identification is valid");
+ DCMTRACT_DEBUG("Checking Track Sets");
if (m_TrackSets.size() > 0)
{
+ DCMTRACT_DEBUG("Found " << m_TrackSets.size() << " Track Sets");
OFVector<TrcTrackSet*>::iterator it = m_TrackSets.begin();
while (it != m_TrackSets.end())
{
+ DCMTRACT_DEBUG("Checking Track Set #" << (it - m_TrackSets.begin() + 1) << "/" << m_TrackSets.size());
if ( (*it)->getNumberOfTracks() == 0)
{
DCMTRACT_ERROR("Track Set does not contain any tracks");
}
else
{
+ DCMTRACT_DEBUG("Track Set contains " << (*it)->getNumberOfTracks() << " tracks, checking them");
OFVector<TrcTrack*> tracks = (*it)->getTracks();
OFVector<TrcTrack*>::iterator t = tracks.begin();
while (t != tracks.end())
return TRC_EC_NoSuchTrack;
}
}
+ else
+ {
+ DCMTRACT_ERROR("Content Identification is not valid");
+ return TRC_EC_InvalidContentIdentification;
+ }
return checkColoring();
}
OFCondition TrcTractographyResultsModule::checkColoring()
{
+ DCMTRACT_DEBUG("Checking Track Set coloring");
size_t tsCount = 1;
OFVector<TrcTrackSet*>::iterator ts = m_TrackSets.begin();
while (ts != m_TrackSets.end())
{
+ DCMTRACT_DEBUG("Checking Track Set coloring for Track Set #" << tsCount << "/" << m_TrackSets.size());
// Collect statistics how much are colored
OFVector<TrcTrack*>::const_iterator track = (*ts)->getTracks().begin();
OFVector<TrcTrack*>::const_iterator last = (*ts)->getTracks().end();
/*
*
- * Copyright (C) 2016-2024, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
OFCondition TrcTrackSet::write(DcmItem& destination)
{
+ DCMTRACT_DEBUG("Writing Track Set");
OFCondition result;
+ DCMTRACT_DEBUG("Writing Track Set Anatomical Type Code Sequence");
DcmIODUtil::writeSingleItem(result, DCM_TrackSetAnatomicalTypeCodeSequence, m_Anatomy, getData(), getRules()->getByTag(DCM_TrackSetAnatomicalTypeCodeSequence));
+ DCMTRACT_DEBUG("Writing Diffusion Acquisition Code Sequence");
DcmIODUtil::writeSingleItem(result, DCM_DiffusionAcquisitionCodeSequence, m_DiffusionAcquisitionCode, getData(), getRules()->getByTag(DCM_DiffusionAcquisitionCodeSequence));
+ DCMTRACT_DEBUG("Writing Diffusion Model Code Sequence");
DcmIODUtil::writeSingleItem(result, DCM_DiffusionModelCodeSequence, m_DiffusionModelCode, getData(), getRules()->getByTag(DCM_DiffusionModelCodeSequence));
+ DCMTRACT_DEBUG("Writing Tracking Algorithm Identification Sequence");
DcmIODUtil::writeSubSequence(result, DCM_TrackingAlgorithmIdentificationSequence, m_TrackingAlgorithmIdentification, getData(), getRules()->getByTag(DCM_TrackingAlgorithmIdentificationSequence));
+ DCMTRACT_DEBUG("Writing Track Statistics");
writeTrackStatistics(result, getData());
+ DCMTRACT_DEBUG("Writing Track Set Statistics");
writeTrackSetStatistics(result, getData());
+ DCMTRACT_DEBUG("Writing Track Set Measurements");
writeMeasurements(result, getData());
+ DCMTRACT_DEBUG("Writing Track Set Tracks");
writeTracks(result, getData());
- if (result.good()) result = IODComponent::write(destination);
+ if (result.good())
+ {
+ DCMTRACT_DEBUG("Writing Track Set details");
+ result = IODComponent::write(destination);
+ }
return result;
}
/*
*
- * Copyright (C) 2016-2024, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
// Common Instance Reference Module
if (result.good()) result = DcmIODCommon::write(dataset);
+ // Write Tractography Results Series attributes which is not covered by a specific class
+ // but part of "this" class
+ if (result.good()) result = IODComponent::write(*getData(), *getRules(), dataset, "TractographyResultsSeries", getValueCheckOnWrite());
+
return result;
}
/*
*
- * Copyright (C) 2016, Open Connections GmbH
+ * Copyright (C) 2016-2025, Open Connections GmbH
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation are maintained by
OFLogger DCM_dcmtractLogger = OFLog::getLogger("dcmtk.dcmtract");
-makeOFConditionConst(TRC_EC_InvalidPointCoordinatesData, OFM_dcmtract, 1, OF_error, "Invalid data in Track's Point Coordinates Data element");
-makeOFConditionConst(TRC_EC_InvalidColorInformation, OFM_dcmtract, 2, OF_error, "Invalid color information for Track or Track Set");
-makeOFConditionConst(TRC_EC_NoSuchTrack, OFM_dcmtract, 3, OF_error, "No such Track in Track Set");
-makeOFConditionConst(TRC_EC_NoSuchMeasurement, OFM_dcmtract, 4, OF_error, "No such Measurement in Track Set");
-makeOFConditionConst(TRC_EC_MeasurementDataMissing, OFM_dcmtract, 5, OF_error, "Measurement misses data for one or more tracks");
-makeOFConditionConst(TRC_EC_InvalidStatisticData, OFM_dcmtract, 6, OF_error, "Statistic data is invalid");
-makeOFConditionConst(TRC_EC_InvalidTrackData, OFM_dcmtract, 7, OF_error, "Track data is invalid");
+makeOFConditionConst(TRC_EC_InvalidPointCoordinatesData, OFM_dcmtract, 1, OF_error, "Invalid data in Track's Point Coordinates Data element");
+makeOFConditionConst(TRC_EC_InvalidColorInformation, OFM_dcmtract, 2, OF_error, "Invalid color information for Track or Track Set");
+makeOFConditionConst(TRC_EC_NoSuchTrack, OFM_dcmtract, 3, OF_error, "No such Track in Track Set");
+makeOFConditionConst(TRC_EC_NoSuchMeasurement, OFM_dcmtract, 4, OF_error, "No such Measurement in Track Set");
+makeOFConditionConst(TRC_EC_MeasurementDataMissing, OFM_dcmtract, 5, OF_error, "Measurement misses data for one or more tracks");
+makeOFConditionConst(TRC_EC_InvalidStatisticData, OFM_dcmtract, 6, OF_error, "Statistic data is invalid");
+makeOFConditionConst(TRC_EC_InvalidTrackData, OFM_dcmtract, 7, OF_error, "Track data is invalid");
+makeOFConditionConst(TRC_EC_InvalidContentIdentification, OFM_dcmtract, 8, OF_error, "Invalid Content Identification for Tractography Results object");
--- /dev/null
+# declare executables
+DCMTK_ADD_TEST_EXECUTABLE(dcmtract_tests
+ tcreate.cc
+ tests.cc
+)
+
+# make sure executables are linked to the corresponding libraries
+DCMTK_TARGET_LINK_MODULES(dcmtract_tests dcmtract)
+
+# This macro parses tests.cc and registers all tests
+DCMTK_ADD_TESTS(dcmtract)
+tcreate.o: tcreate.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/dcmtract/trctractographyresults.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdeprec.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/vsconstexp.def \
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modfor.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \
+ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
+ ../include/dcmtk/dcmtract/trctrackset.h \
+ ../../dcmiod/include/dcmtk/dcmiod/iodutil.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdate.h \
+ ../../ofstd/include/dcmtk/ofstd/oftime.h \
+ ../include/dcmtk/dcmtract/trctypes.h ../include/dcmtk/dcmtract/trcdef.h \
+ ../include/dcmtk/dcmtract/trcmodtractresults.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../ofstd/include/dcmtk/ofstd/oftempf.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h
+tests.o: tests.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
+ ../../oflog/include/dcmtk/oflog/oflog.h \
+ ../../oflog/include/dcmtk/oflog/logger.h \
+ ../../oflog/include/dcmtk/oflog/config.h \
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
+ ../../oflog/include/dcmtk/oflog/tstring.h \
+ ../../oflog/include/dcmtk/oflog/tchar.h \
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
+ ../../oflog/include/dcmtk/oflog/appender.h \
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
+ ../../oflog/include/dcmtk/oflog/layout.h \
+ ../../oflog/include/dcmtk/oflog/streams.h \
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
+ ../../oflog/include/dcmtk/oflog/tracelog.h
@SET_MAKE@
SHELL = /bin/sh
+VPATH = @srcdir@:@top_srcdir@/include:@top_srcdir@/@configdir@/include
srcdir = @srcdir@
top_srcdir = @top_srcdir@
configdir = @top_srcdir@/@configdir@
include $(configdir)/@common_makefile@
+oficonvdir = $(top_srcdir)/../oficonv
+ofstddir = $(top_srcdir)/../ofstd
+oflogdir = $(top_srcdir)/../oflog
+dcmdatadir = $(top_srcdir)/../dcmdata
+dcmioddir = $(top_srcdir)/../dcmiod
+dcmfgdir = $(top_srcdir)/../dcmfg
-all:
+LOCALINCLUDES = -I$(top_srcdir)/include -I$(ofstddir)/include -I$(oflogdir)/include \
+ -I$(dcmdatadir)/include -I$(dcmioddir)/include -I$(dcmfgdir)/include
+LIBDIRS = -L$(top_srcdir)/libsrc -L$(oficonvdir)/libsrc -L$(ofstddir)/libsrc \
+ -L$(oflogdir)/libsrc -L$(dcmdatadir)/libsrc -L$(dcmioddir)/libsrc \
+ -L$(dcmfgdir)/libsrc
+LOCALLIBS = -ldcmtract -ldcmfg -ldcmiod -ldcmdata -loflog -lofstd -loficonv \
+ $(ZLIBLIBS) $(CHARCONVLIBS) $(MATHLIBS)
-check:
+test_objs = tcreate.o tests.o
-check-exhaustive:
+objs = $(test_objs)
+progs = tests
+
+
+all: $(progs)
+
+tests: $(test_objs)
+ $(CXX) $(CXXFLAGS) $(LIBDIRS) $(LDFLAGS) -o $@ $(test_objs) $(LOCALLIBS) $(LIBS)
+
+
+check: tests
+ DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests
+
+check-exhaustive: tests
+ DCMDICTPATH=../../dcmdata/data/dicom.dic ./tests -x
+
+
+install: all
-install:
clean:
- rm -f $(TRASH)
+ rm -f $(objs) $(progs) $(TRASH)
distclean:
- rm -f $(DISTTRASH)
+ rm -f $(objs) $(progs) $(DISTTRASH)
+
dependencies:
+ $(CXX) -MM $(defines) $(includes) $(CPPFLAGS) $(CXXFLAGS) *.cc > $(DEP)
+
+include $(DEP)
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmtract
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: Tests that check for pixel data overflow conditions
+ *
+ */
+
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+
+#include "dcmtk/dcmtract/trctractographyresults.h"
+#include "dcmtk/dcmdata/dcfilefo.h"
+#include "dcmtk/ofstd/oftest.h"
+#include "dcmtk/ofstd/oftempf.h"
+#include "dcmtk/dcmdata/dcdict.h"
+
+static OFString EXPECTED_DUMP;
+
+static TrcTractographyResults *create();
+static void setGenericValues(TrcTractographyResults *ct);
+
+
+OFTEST(dcmtract_create)
+{
+ /* make sure data dictionary is loaded */
+ if (!dcmDataDict.isDictionaryLoaded())
+ {
+ OFCHECK(dcmDataDict.isDictionaryLoaded());
+ }
+
+ // Creation
+ TrcTractographyResults* tract(create());
+ OFCHECK(tract != OFnullptr);
+
+
+ setGenericValues(tract);
+
+ // Write to dataset and compare its dump with expected result
+ DcmFileFormat dcmff;
+
+ // We just use this to create a temporary file name
+ OFTempFile tf(O_RDWR, "", "dcmtract_create", ".dcm");
+ OFCondition result;
+ result = tract->saveFile(tf.getFilename(), EXS_LittleEndianExplicit);
+ OFCHECK_MSG(result == EC_Normal, result.text());
+ delete tract; // delete tractography results object
+}
+
+static TrcTractographyResults *create()
+{
+ IODEnhGeneralEquipmentModule::EquipmentInfo eq("Open Connections", "OC CT", "4711", "0.1");
+ TrcTractographyResults *tract = NULL;
+ OFCondition result;
+ result = TrcTractographyResults::create(ContentIdentificationMacro("1", "LABEL", "Description", "Open Connections"),
+ "20250527",
+ "103100",
+ eq,
+ IODReferences(),
+ tract);
+
+ OFCHECK(result.good());
+ OFCHECK(tract != OFnullptr);
+ return tract;
+}
+
+
+static void setGenericValues(TrcTractographyResults *tract)
+{
+ if (!tract)
+ return;
+ OFCHECK(tract->getPatient().setPatientName("Bond^James").good());
+ OFCHECK(tract->getPatient().setPatientID("007").good());
+ OFCHECK(tract->getPatient().setPatientBirthDate("19771007").good());
+ OFCHECK(tract->getStudy().setStudyDate("20250101").good());
+ OFCHECK(tract->getStudy().setStudyTime("120000").good());
+ OFCHECK(tract->getStudy().setStudyID("1").good());
+ OFCHECK(tract->getPatientStudy().setPatientAge("047Y").good());
+ OFCHECK(tract->getSeries().setSeriesDescription("Test Description").good());
+ OFCHECK(tract->getSeries().setSeriesNumber("1").good());
+
+ // Those values are usually computed automatically. UIDS are generated and date/times are set to current values.
+ // But in order to compare the "old" dump with the freshly created image attributes, we set some values manually,
+ // so that they are not overwritten with new, automatically created values later.
+ OFCHECK(tract->getStudy().setStudyInstanceUID("1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811").good());
+ OFCHECK(tract->getFrameOfReference().setFrameOfReferenceUID("2.25.30853397773651184949181049330553108086").good());
+ OFCHECK(tract->getSeries().setSeriesInstanceUID("1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812").good());
+ OFCHECK(tract->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good());
+
+ // Create trackset
+ CodeWithModifiers trackSetAnatomy("3", "1");
+ trackSetAnatomy.set("12738006", "SCT", "Brain");
+ // Create algo identification macro
+ AlgorithmIdentificationMacro algo;
+ algo.getAlgorithmFamilyCode().set("4711", "99OC", "Dummy Tracking");
+ algo.setAlgorithmName("Deterministic Tracking");
+ algo.setAlgorithmVersion("1.0");
+ algo.setAlgorithmParameters("Parameter1=Value1\\Parameter2=Value2");
+ algo.setAlgorithmSource("Open Connections");
+
+ TrcTrackSet* tractSet = NULL;
+
+ // Add trackset to tractography results
+ OFCondition result = tract->addTrackSet("TRACK_SET_LABEL", "Track Set Description",
+ trackSetAnatomy,
+ CodeSequenceMacro("113231", "DCM", "Single Tensor"),
+ algo, tractSet);
+
+ OFCHECK(result.good());
+ OFCHECK(tractSet != OFnullptr);
+
+ // Add tracks to trackset
+ Float32 points[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f };
+ Uint16 colors[] = { 0, 0, 0 };
+ TrcTrack* track = NULL;
+ result = tractSet->addTrack(points, 2, colors, 1, track);
+ OFCHECK(result.good());
+ OFCHECK(track != OFnullptr);
+}
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: dcmtract
+ *
+ * Author: Michael Onken
+ *
+ * Purpose: main test program
+ *
+ */
+
+#include "dcmtk/config/osconfig.h"
+
+#include "dcmtk/ofstd/oftest.h"
+
+OFTEST_REGISTER(dcmtract_create);
+
+OFTEST_MAIN("dcmtract")
DCMTK_ADD_EXECUTABLE(wlmscpfs wlmscpfs.cc wlcefs.cc)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(wlmscpfs dcmwlm dcmnet dcmtls dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(wlmscpfs dcmwlm)
/*
*
- * Copyright (C) 1996-2024, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
cmd->addOption("--no-sq-expansion", "-nse", "disable expansion of empty sequences in C-FIND\nrequest messages");
cmd->addGroup("network options:");
+ cmd->addSubGroup("IP protocol version:");
+ cmd->addOption("--ipv4", "-i4", "use IPv4 only (default)");
+ cmd->addOption("--ipv6", "-i6", "use IPv6 only");
+ cmd->addOption("--ip-auto", "-i0", "use IPv6/IPv4 dual stack");
+
cmd->addSubGroup("preferred network transfer syntaxes:");
cmd->addOption("--prefer-uncompr", "+x=", "prefer explicit VR local byte order (default)");
cmd->addOption("--prefer-little", "+xe", "prefer explicit VR little endian TS");
if( cmd->findOption("--no-sq-expansion") ) opt_noSequenceExpansion = OFTrue;
// network options
+
+ // set the IP protocol version
+ cmd->beginOptionBlock();
+ if (cmd->findOption("--ipv4")) dcmIncomingProtocolFamily.set(ASC_AF_INET);
+ if (cmd->findOption("--ipv6")) dcmIncomingProtocolFamily.set(ASC_AF_INET6);
+ if (cmd->findOption("--ip-auto")) dcmIncomingProtocolFamily.set(ASC_AF_UNSPEC);
+ cmd->endOptionBlock();
+
cmd->beginOptionBlock();
if( cmd->findOption("--prefer-uncompr") ) opt_networkTransferSyntax = EXS_Unknown;
if( cmd->findOption("--prefer-little") ) opt_networkTransferSyntax = EXS_LittleEndianExplicit;
\subsection wlmscpfs_network_options network options
\verbatim
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
preferred network transfer syntaxes:
+x= --prefer-uncompr
(0010,1080) MilitaryRank
(0010,2000) MedicalAlerts
(0010,2110) ContrastAllergies
-(0010,2160) EthnicGroup
+(0010,2160) EthnicGroup (retired)
(0010,21a0) SmokingStatus
(0010,21b0) AdditionalPatientHistory
(0010,21c0) PregnancyStatus
\section wlmscpfs_copyright COPYRIGHT
-Copyright (C) 1996-2024 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
+Copyright (C) 1996-2025 by OFFIS e.V., Escherweg 2, 26121 Oldenburg, Germany.
*/
/*
*
- * Copyright (C) 1996-2023, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* DCM_AdmittingDiagnosesDescription (0008,1080) LO O 3 (from the Visit Admission Module)
* DCM_RETIRED_OtherPatientIDs (0010,1000) LO O 3 (from the Patient Identification Module)
* DCM_PatientSize (0010,1020) DS O 3 (from the Patient Demographic Module)
- * DCM_EthnicGroup (0010,2160) SH O 3 (from the Patient Demographic Module)
+ * DCM_RETIRED_EthnicGroup (0010,2160) SH O 3 (from the Patient Demographic Module)
* DCM_PatientComments (0010,4000) LT O 3 (from the Patient Demographic Module)
* DCM_AdditionalPatientHistory (0010,21b0) LT O 3 (from the Patient Medical Module)
* DCM_LastMenstrualDate (0010,21d0) DA O 3 (from the Patient Medical Module)
/*
*
- * Copyright (C) 1996-2023, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// DCM_AdmittingDiagnosesDescription (0008,1080) LO O 3 (from the Visit Admission Module)
// DCM_RETIRED_OtherPatientIDs (0010,1000) LO O 3 (from the Patient Identification Module)
// DCM_PatientSize (0010,1020) DS O 3 (from the Patient Demographic Module)
-// DCM_EthnicGroup (0010,2160) SH O 3 (from the Patient Demographic Module)
+// DCM_RETIRED_EthnicGroup (0010,2160) SH O 3 (from the Patient Demographic Module)
// DCM_PatientComments (0010,4000) LT O 3 (from the Patient Demographic Module)
// DCM_AdditionalPatientHistory (0010,21b0) LT O 3 (from the Patient Medical Module)
// DCM_LastMenstrualDate (0010,21d0) DA O 3 (from the Patient Medical Module)
elementKey == DCM_AdmittingDiagnosesDescription ||
elementKey == DCM_RETIRED_OtherPatientIDs ||
elementKey == DCM_PatientSize ||
- elementKey == DCM_EthnicGroup ||
+ elementKey == DCM_RETIRED_EthnicGroup ||
elementKey == DCM_PatientComments ||
elementKey == DCM_AdditionalPatientHistory ||
elementKey == DCM_LastMenstrualDate ||
/*
*
- * Copyright (C) 1996-2023, OFFIS e.V.
+ * Copyright (C) 1996-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" // specific configuration for operating system
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> // for O_RDWR
-#endif
END_EXTERN_C
#include "dcmtk/ofstd/oftypes.h"
#include "dcmtk/ofstd/ofstd.h"
DCMTK_ADD_TEST_EXECUTABLE(wltest wltest.cc)
# make sure executables are linked to the corresponding libraries
-DCMTK_TARGET_LINK_MODULES(wltest dcmwlm dcmnet dcmtls dcmdata oflog ofstd)
+DCMTK_TARGET_LINK_MODULES(wltest dcmwlm dcmtls)
--- /dev/null
+ANNOUNCEMENT
+
+Version 3.6.9 of the OFFIS DCMTK (DICOM toolkit) software is now available for
+public release. This release includes the following main changes over the
+previous version 3.6.8:
+
+- DCMTK 3.6.9 builds correctly on older and up-to-date versions of GNU gcc
+ (9.5.0 to 14.2.0), Clang (14.0.6 to 18.1.8), Apple Clang (14.0.3 to 15.0.0),
+ and Microsoft Visual Studio (2017 to 2022).
+
+- Tested with the following operating systems/environments:
+ - Android on arm64
+ - FreeBSD on x86_64
+ - Linux on x86_64 and x86
+ - MacOS X on x86_64 and arm64
+ - NetBSD on x86_64
+ - OpenBSD on x86_64
+ - OpenIndiana on x86_64
+ - Windows (including MinGW) on x86_64 and x86
+
+ For a complete list of tested systems and compilers, see the INSTALL file.
+
+- Updated DICOM data dictionary, list of SOP classes, well-known frame of
+ references, transfer syntaxes, code definitions, supported context group
+ classes, and directory record types for DICOM standard release 2024e:
+
+ - This also includes the latest attributes and SOP classes for the DICONDE
+ standard, e.g. for thermography images (based on ASTM E3440).
+
+ - Also updated the DICOMDIR generation code and tools accordingly.
+
+
+- The new JPEG XL and HTJ2K transfer syntaxes as well as the encapsulated
+ uncompressed transfer syntax are now supported for reading and writing, i.e.
+ for both files and network transfer. However, encoders or decoders have not
+ been implemented yet.
+
+- Added new command line tool dcm2img that unifies and replaces the tools
+ dcm2pnm, dcmj2pnm and dcml2pnm, and adds support for JPEG-LS as an export
+ format for image files. The command line options are identical to the older
+ tools, so that dcm2img can serve as a drop-in replacement:
+
+ - By default, the new command line tool determines the output format
+ automatically based on the extension of the output filename.
+
+ - The deprecated command line tools were replaced by stubs, which are provided
+ for the user's convenience, but will be removed with a future release.
+
+- Added new command line tool dcm2cda that extracts a CDA document from a DICOM
+ Encapsulated CDA Storage SOP Instance and stores it in a separate file.
+
+- Replaced command line tool dcmgpdir by a stub that calls the more
+ comprehensive command line tool dcmmkdir.
+
+- Further enhanced and updated DICOM Structured Reporting (SR) module "dcmsr":
+
+ - Added support for the new Waveform Annotation SR IOD (introduced with
+ Supplement 239).
+
+ - Made URL prefix for hyperlinks to composite objects configurable.
+
+ - Updated code definitions and supported context group classes (see above).
+
+ - Fixed issue with various IOD constraint checkers (see CP-2084).
+
+- Added IPv6 support to DCMTK's association requestors. All DCMTK "client"
+ applications that only request outgoing DICOM network associations can now
+ explicitly select the protocol version to be used. IPv6 support is not yet
+ implemented for association acceptors ("server" applications).
+
+- Various TLS enhancements:
+
+ - Added TLS support to the command line tools dcmqrscp and getscu.
+
+ - Added support for the Modified BCP 195 RFC 8996 TLS Profile.
+
+ - Added new command line option --list-profiles to all TLS-enabled tools.
+ This option prints a list of the TLS Secure Transport Connection Profiles
+ supported.
+
+ - Removed support for OpenSSL 1.0.2 and 1.1.0 and added support for OpenSSL
+ 3.1.0 to 3.4.0.
+
+- Extended central DCMTK data structure where all SOP Classes are defined with
+ their associated properties, e.g. type and sub-type.
+
+- Largely enhanced basic transfer syntax class DcmXfer, e.g. to distinguish
+ more clearly between encapsulation and compression. Please note that some of
+ the old methods have been deprecated and will be removed in a future release.
+
+- Enhanced performance of OFGlobal class, especially when used in applications
+ with many threads that read global objects of this class concurrently.
+
+- New, fully standards compliant implementations of OFStandard::atof() and
+ OFStandard::ftoa(), DCMTK's locale independent conversion routines between
+ floating point numbers and text.
+
+- Removed support for ICU-based character set conversion. Since the oficonv
+ module in DCMTK supports all DICOM Specific Character Sets, the ICU support,
+ which was never complete, has been removed.
+
+- DCMTK now requires compilers to provide conformance to C++98 and supports
+ compilation with newer C++ versions up to C++20, which can be enabled via
+ CMake's CMAKE_CXX_STANDARD variable. By default, C++11 is now enabled on
+ compilers that support this.
+
+- CMake-related enhancements and other changes:
+
+ - The configure process now respects CMake's CMAKE_CROSSCOMPILING_EMULATOR
+ variable.
+
+ - Exposed the CMAKE_DEBUG_POSTFIX variable to the user. There are extra
+ options to also enable the postfix for Windows DLLs as well as executables.
+
+- Many configure tests related to outdated compilers or libraries were removed,
+ thus significantly speeding up the configuration process.
+
+- Fixed binary segmentations with certain dimensions (some cases where number
+ of total bits per frame is not divisible by 8) that were broken when being
+ serialized into a dataset.
+
+- Fixed various other issues that occurred after the official 3.6.8 release,
+ and further improved the performance. See CHANGES file for details.
+
+Many people have contributed to this new release of DCMTK, appearing here in
+alphabetical order. Thank you very much for your support!
+
+ Christian Wetzel <wetzel@phoenix-pacs.de>
+ David Gobbi <david.gobbi@gmail.com>
+ David Seifert <soap@gentoo.org>
+ Giulio Simonetti <giulio.simonetti@datamind.biz>
+ Helmut Steiner <helmut@shl.at>
+ Jean Pierre Bassenge <jp.bassenge@fiagon.com>
+ Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
+ Jesper Alf Dam <Jesper.Dam@mi.medical.canon>
+ Kevin Leonardic <kevin@leonardic.de>
+ Marcel Pham <Marcel.Pham@examion.com>
+ Mario Galijot <mario@salaourn.com>
+ Markus Sabin <Markus.Sabin@soft-gate.de>
+ Martin Zeiser of the Cisco Talos team <vulndiscovery@external.cisco.com>
+ Mathieu Malaterre <mathieu.malaterre@gmail.com>
+ Matt McCormick <matt.mccormick@kitware.com>
+ Melanie Michels <melanie.michels@snkeos.com>
+ Nils Bars <nils.bars@rub.de>
+ Peter Klotz <peter.klotz@siemens-healthineers.com>
+ Phileas Lebada <phileas@contextflow.com>
+ Piotr Batko <Piotr.Batko@gehealthcare.com>
+ Sam James <sam@gentoo.org>
+ Sobhita Mercy <sobhitamercy@gmail.com>
+ Yoshinaga Kosuke <kosuke.yoshinaga@goodmankk.com>
+
+ DCMTK forum users "andreasb", "Fabian Guenther", "nbeck", "Oleh", "saltcreek"
+
+ GitHub users "akaraivanov", "bananabr", "khangthk", "luissantosHCIT",
+ "malaterre", "mrbean-bremen", "percontation", "thewtex"
+
+Members of the DCMTK Team who have worked on this release are:
+
+ Joerg Riesmeier <dicom@jriesmeier.com>
+ Marco Eichelberg <eichelberg@offis.de>
+ Michael Onken <onken@open-connections.de>
+ Tingyan Xu <tingyan.xu@offis.de>
+
+The DCMTK software can be downloaded via:
+
+ https://dicom.offis.de/dcmtk or https://www.dcmtk.org/
+
+OFFIS e.V., Oldenburg, Germany, 2024-12-10
--- /dev/null
+
+Release 3.7.0 (Public Minor Release - 2025-12-15)
+
+**** Changes from 2025.12.15 (eichelberg)
+
+- Created CHANGES.370 for DCMTK release 3.7.0:
+ CHANGES.370 contains the Git commit history since DCMTK release 3.6.9.
+ Added: docs/CHANGES.370
+
+- Updated man pages for DCMTK release 3.7.0.
+ Added: doxygen/manpages/man1/dcmdecap.1
+ doxygen/manpages/man1/dcmencap.1
+ doxygen/manpages/man1/json2dcm.1
+ Affects: doxygen/manpages/man1/cda2dcm.1
+ doxygen/manpages/man1/dcm2cda.1
+ doxygen/manpages/man1/dcm2img.1
+ doxygen/manpages/man1/dcm2json.1
+ doxygen/manpages/man1/dcm2pdf.1
+ doxygen/manpages/man1/dcm2pnm.1
+ doxygen/manpages/man1/dcm2xml.1
+ doxygen/manpages/man1/dcmcjpeg.1
+ doxygen/manpages/man1/dcmcjpls.1
+ doxygen/manpages/man1/dcmconv.1
+ doxygen/manpages/man1/dcmcrle.1
+ doxygen/manpages/man1/dcmdjpeg.1
+ doxygen/manpages/man1/dcmdjpls.1
+ doxygen/manpages/man1/dcmdrle.1
+ doxygen/manpages/man1/dcmdspfn.1
+ doxygen/manpages/man1/dcmdump.1
+ doxygen/manpages/man1/dcmftest.1
+ doxygen/manpages/man1/dcmgpdir.1
+ doxygen/manpages/man1/dcmicmp.1
+ doxygen/manpages/man1/dcmj2pnm.1
+ doxygen/manpages/man1/dcml2pnm.1
+ doxygen/manpages/man1/dcmmkcrv.1
+ doxygen/manpages/man1/dcmmkdir.1
+ doxygen/manpages/man1/dcmmklut.1
+ doxygen/manpages/man1/dcmodify.1
+ doxygen/manpages/man1/dcmp2pgm.1
+ doxygen/manpages/man1/dcmprscp.1
+ doxygen/manpages/man1/dcmprscu.1
+ doxygen/manpages/man1/dcmpschk.1
+ doxygen/manpages/man1/dcmpsmk.1
+ doxygen/manpages/man1/dcmpsprt.1
+ doxygen/manpages/man1/dcmpsrcv.1
+ doxygen/manpages/man1/dcmpssnd.1
+ doxygen/manpages/man1/dcmqridx.1
+ doxygen/manpages/man1/dcmqrscp.1
+ doxygen/manpages/man1/dcmqrti.1
+ doxygen/manpages/man1/dcmquant.1
+ doxygen/manpages/man1/dcmrecv.1
+ doxygen/manpages/man1/dcmscale.1
+ doxygen/manpages/man1/dcmsend.1
+ doxygen/manpages/man1/dcmsign.1
+ doxygen/manpages/man1/dcod2lum.1
+ doxygen/manpages/man1/dconvlum.1
+ doxygen/manpages/man1/drtdump.1
+ doxygen/manpages/man1/dsr2html.1
+ doxygen/manpages/man1/dsr2xml.1
+ doxygen/manpages/man1/dsrdump.1
+ doxygen/manpages/man1/dump2dcm.1
+ doxygen/manpages/man1/echoscu.1
+ doxygen/manpages/man1/findscu.1
+ doxygen/manpages/man1/getscu.1
+ doxygen/manpages/man1/img2dcm.1
+ doxygen/manpages/man1/mkcsmapper.1
+ doxygen/manpages/man1/mkesdb.1
+ doxygen/manpages/man1/movescu.1
+ doxygen/manpages/man1/pdf2dcm.1
+ doxygen/manpages/man1/stl2dcm.1
+ doxygen/manpages/man1/storescp.1
+ doxygen/manpages/man1/storescu.1
+ doxygen/manpages/man1/termscu.1
+ doxygen/manpages/man1/wlmscpfs.1
+ doxygen/manpages/man1/xml2dcm.1
+ doxygen/manpages/man1/xml2dsr.1
+
+- Updated version information for DCMTK release 3.7.0.
+ Affects: CMake/dcmtkPrepare.cmake
+
+- Updated copyright date.
+ Affects: dcmdata/docs/dcm2xml.man
+ dcmdata/docs/dcmconv.man
+ dcmdata/docs/dcmcrle.man
+ dcmdata/docs/dcmdrle.man
+ dcmdata/docs/dcmdump.man
+ dcmdata/docs/dcmftest.man
+ dcmdata/docs/dcmgpdir.man
+ dcmdata/docs/dcmodify.man
+ dcmdata/docs/dump2dcm.man
+ dcmdata/docs/img2dcm.man
+ dcmdata/docs/xml2dcm.man
+ dcmimage/docs/dcm2pnm.man
+ dcmimage/docs/dcmicmp.man
+ dcmimage/docs/dcmquant.man
+ dcmimage/docs/dcmscale.man
+ dcmimgle/docs/dcmdspfn.man
+ dcmimgle/docs/dcod2lum.man
+ dcmimgle/docs/dconvlum.man
+ dcmjpeg/docs/dcmcjpeg.man
+ dcmjpeg/docs/dcmj2pnm.man
+ dcmjpeg/docs/dcmmkdir.man
+ dcmjpls/docs/dcmcjpls.man
+ dcmjpls/docs/dcmdjpls.man
+ dcmjpls/docs/dcml2pnm.man
+ dcmnet/docs/dcmsend.man
+ dcmnet/docs/findscu.man
+ dcmnet/docs/storescu.man
+ dcmnet/docs/termscu.man
+ dcmpstat/docs/dcmmkcrv.man
+ dcmpstat/docs/dcmmklut.man
+ dcmpstat/docs/dcmp2pgm.man
+ dcmpstat/docs/dcmpschk.man
+ dcmpstat/docs/dcmpsmk.man
+ dcmpstat/docs/dcmpsprt.man
+ dcmpstat/docs/dcmpsrcv.man
+ dcmpstat/docs/dcmpssnd.man
+ dcmqrdb/docs/dcmqridx.man
+ dcmqrdb/docs/dcmqrti.man
+ dcmrt/docs/drtdump.man
+ dcmsign/docs/dcmsign.man
+
+- Updated autoconf files for upcoming release.
+ Affects: VERSION
+ config/configure
+ config/configure.in
+ config/confmod
+
+- Updated URL for Windows support libs.
+ Affects: .github/workflows/cmake-win.yml
+
+- Updated documentation for upcoming release.
+ Affects: ANNOUNCE
+ CREDITS
+ INSTALL
+
+**** Changes from 2025.12.12 (eichelberg)
+
+- Fixed warnings reported on Android.
+ Affects: dcmpstat/apps/dcmpssnd.cc
+ dcmqrdb/libsrc/dcmqrcbg.cc
+ dcmqrdb/libsrc/dcmqrcbm.cc
+ dcmqrdb/libsrc/dcmqrdbi.cc
+ dcmqrdb/libsrc/dcmqrsrv.cc
+ dcmqrdb/libsrc/dcmqrtis.cc
+ ofstd/include/dcmtk/ofstd/ofstd.h
+ ofstd/libsrc/offilsys.cc
+
+- Fixed documentation:
+ Fixed an incorrect API documentation.
+ Thanks to Matt Hancock <mhancock@innolitics.com> for the report.
+ Affects: dcmnet/include/dcmtk/dcmnet/scp.h
+ dcmnet/include/dcmtk/dcmnet/scpcfg.h
+
+**** Changes from 2025.12.11 (goldhammer)
+
+- Updated CMake files for Android API 35:
+ Updated the CMake toolchain for Android API level 35 and Android NDK R27.
+ Affects: CMake/CTest/CTestCustomAndroid.cmake.in
+ CMake/CTest/dcmtkCTestRunAndroid.cmake.in
+ CMake/dcmtkMacros.cmake
+ CMake/dcmtkUseAndroidSDK.cmake
+ CMakeLists.txt
+
+**** Changes from 2025.12.09 (riesmeier)
+
+- Avoid wrong warning message on private pixel data:
+ Made sure that a warning message on compressed private pixel data is
+ only reported if the element length is really undefined.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the
+ original report.
+ Affects: dcmdata/libsrc/dcitem.cc
+
+**** Changes from 2025.12.08 (riesmeier)
+
+- Fixed issue when charset conversion is disabled:
+ Fixed compilation error when character set conversion has been disabled
+ during configuration process.
+ Affects: dcmsr/apps/dsrdump.cc
+
+**** Changes from 2025.12.02 (eichelberg)
+
+- Fixed bug in handling of odd-length data elements:
+ When a dataset containing an illegal odd-length attribute with a text VR
+ was read from file or received over a network connection, then accessing
+ the value of that attribute with DcmElement::getString() may return a
+ pointer to a string that was not properly null terminated. Using C string
+ functions such as strlen() or strcpy() on that string then lead to a read
+ beyond the end of a string, causing a segmentation fault.
+ Thanks to Zou Dikai <zoudikai@outlook.com> for the bug report and POC.
+ This closes DCMTK issue #1184.
+ Affects: dcmdata/libsrc/dcbytstr.cc
+
+**** Changes from 2025.11.28 (riesmeier)
+
+- Updated information on latest CMake version:
+ Changed latest CMake version that was tested to 4.2.0.
+ Affects: CMakeLists.txt
+
+**** Changes from 2025.11.28 (eichelberg)
+
+- Fixed two possible segfaults in dcmqrscp:
+ Fixed two places where invalid messages may trigger a segmentation fault
+ due to a NULL pointer being de-referenced.
+ Thanks to 邹 迪凯 <zoudikai@outlook.com> for the bug report and proof-of-concept.
+ Affects: dcmqrdb/libsrc/dcmqrdbi.cc
+
+**** Changes from 2025.11.27 (eichelberg)
+
+- Fixed errors when compiling with C++98.
+ Affects: dcmseg/include/dcmtk/dcmseg/overlaputil.h
+ dcmseg/libsrc/segdoc.cc
+
+**** Changes from 2025.11.26 (onken)
+
+- Fix compiler warning on unreachable code.
+ Affects: dcmseg/libsrc/overlaputil.cc
+
+**** Changes from 2025.11.26 (eichelberg)
+
+- Fixed strlcpy related issue in oficonv:
+ Replaced two calls of strlcpy with strncpy in places where the source
+ string is not guaranteed to be always null terminated, which strlcpy requires.
+ Thanks to DCMTK forum user "saltcreek" for the original report.
+ Affects: oficonv/libsrc/citrus_mapper.c
+
+**** Changes from 2025.11.25 (onken)
+
+- Avoid compiler warning for VS 2022 on Windows 10.
+ Affects: dcmseg/libsrc/overlaputil.cc
+
+**** Changes from 2025.11.25 (riesmeier)
+
+- Fixed wrong use of ESC in "LO" and "SH" test case:
+ Thanks to GitHub user "mrbean-bremen" for the original report and
+ proposed patch (see PR #124).
+ Affects: dcmdata/tests/tchval.cc
+
+- Updated copyright date.
+ Affects: COPYRIGHT
+
+**** Changes from 2025.11.25 (onken)
+
+- Fix compiler warnings/errors from 74bba5.
+ Affects: dcmfg/include/dcmtk/dcmfg/framesorter.h
+ dcmseg/include/dcmtk/dcmseg/overlaputil.h
+ dcmseg/libsrc/overlaputil.cc
+ dcmseg/libsrc/segment.cc
+
+**** Changes from 2025.11.24 (onken)
+
+- Re-add dcmsign to the Makefile:
+ Accidentally removed in the last commit.
+ Affects: Makefile
+
+- OverlapUtil and some segmentation enhancements:
+ Added OverlapUtil class which allows to detect whether a binary
+ segmentation contains overlapping segments. This supports an upcoming
+ converter for converting binary segmentation objects into labelmap
+ segmentations.
+ Various small enhancements.
+ Added: dcmfg/include/dcmtk/dcmfg/framesorter.h
+ dcmiod/include/dcmtk/dcmiod/iccexample.h
+ dcmiod/tests/tmacro.cc
+ dcmseg/include/dcmtk/dcmseg/overlaputil.h
+ dcmseg/libsrc/overlaputil.cc
+ Affects: Makefile
+ config/math.cc
+ dcmdata/apps/Makefile.dep
+ dcmdata/libsrc/Makefile.dep
+ dcmect/libsrc/Makefile.dep
+ dcmect/tests/Makefile.dep
+ dcmfg/libsrc/Makefile.dep
+ dcmfg/libsrc/fginterface.cc
+ dcmfg/tests/Makefile.dep
+ dcmiod/include/dcmtk/dcmiod/iodrules.h
+ dcmiod/include/dcmtk/dcmiod/iodtypes.h
+ dcmiod/include/dcmtk/dcmiod/modequipment.h
+ dcmiod/include/dcmtk/dcmiod/modiccprofile.h
+ dcmiod/libsrc/Makefile.dep
+ dcmiod/libsrc/iodmacro.cc
+ dcmiod/libsrc/iodrules.cc
+ dcmiod/libsrc/modequipment.cc
+ dcmiod/libsrc/modiccprofile.cc
+ dcmiod/tests/CMakeLists.txt
+ dcmiod/tests/Makefile.dep
+ dcmiod/tests/Makefile.in
+ dcmiod/tests/tests.cc
+ dcmpmap/libsrc/Makefile.dep
+ dcmseg/Makefile.in
+ dcmseg/include/dcmtk/dcmseg/segdoc.h
+ dcmseg/include/dcmtk/dcmseg/segment.h
+ dcmseg/include/dcmtk/dcmseg/segtypes.h
+ dcmseg/include/dcmtk/dcmseg/segutils.h
+ dcmseg/libsrc/CMakeLists.txt
+ dcmseg/libsrc/Makefile.dep
+ dcmseg/libsrc/Makefile.in
+ dcmseg/libsrc/segdoc.cc
+ dcmseg/libsrc/segment.cc
+ dcmseg/libsrc/segtypes.cc
+ dcmseg/libsrc/segutils.cc
+ dcmseg/tests/Makefile.dep
+ dcmseg/tests/Makefile.in
+ dcmsr/apps/Makefile.dep
+ dcmsr/libsrc/Makefile.dep
+ dcmsr/tests/Makefile.dep
+ dcmtract/libsrc/Makefile.dep
+ dcmtract/tests/Makefile.dep
+ ofstd/include/dcmtk/ofstd/ofmath.h
+ ofstd/libsrc/ofmath.cc
+
+**** Changes from 2025.11.23 (onken)
+
+- Updated copyright date.
+ Affects: dcmnet/include/dcmtk/dcmnet/scppool.h
+
+- Fix potential crashes and endless loop:
+ Fix crash when worker thread reports to the owner pool after destructor
+ of the pool was called.
+ There is no guarantee that all worker threads have completed their work
+ when when m_runMode is set to SHUTDOWN. Added an additional condition to
+ the while loop to wait until all workers have completed their tasks and
+ reported to the pool. After that it's guarantied that all workers are in
+ the m_workerIdle list and can be safely joined.
+ ---
+ Fixed two cases that make destructor of DcmBaseSCPPool never exit.
+ Current implementation of DcmBaseSCPPool's destructor waits for the
+ m_runMode to be set to SHUTDOWN. If m_runMode never set to SHUTDOWN the
+ destructor will wait forever in the 'while' cycle. Two cases when
+ m_runMode is not set to SHUTDOWN:
+ Case 1: The m_runMode won't be set to SHUTDOWN if
+ DcmBaseSCPPool::listen() was never called.
+ Fix:
+ Changed default value of m_runMode from LISTEN to SHUTDOWN. The
+ m_runMode is set to LISTEN inside of the DcmBaseSCPPool::listen()
+ function.
+ Case 2:
+ Call to initializeNetwork() in the DcmBaseSCPPool::listen() function
+ might return bad condition. In that case m_runMode won't be set to
+ SHUTDOWN due to early return.
+ Fix:
+ Add a call to the newly added finishListening() function in case of
+ early return.
+ Thanks to GitHub user Vovasch for the report and patch.
+ Affects: dcmnet/include/dcmtk/dcmnet/scppool.h
+ dcmnet/libsrc/scppool.cc
+
+**** Changes from 2025.11.21 (riesmeier)
+
+- Updated Context Group classes for DICOM 2025e:
+ Updated automatically generated Context Group classes for the latest
+ release of the DICOM standard. All supported classes were updated,
+ even though there were no changes to most of them.
+ Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid11.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid218.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid244.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid247.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid29.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid42.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7551.h
+ dcmsr/libcmr/cid100.cc
+ dcmsr/libcmr/cid10013.cc
+ dcmsr/libcmr/cid10033.cc
+ dcmsr/libcmr/cid11.cc
+ dcmsr/libcmr/cid218.cc
+ dcmsr/libcmr/cid244.cc
+ dcmsr/libcmr/cid247.cc
+ dcmsr/libcmr/cid29.cc
+ dcmsr/libcmr/cid4020.cc
+ dcmsr/libcmr/cid4021.cc
+ dcmsr/libcmr/cid4031.cc
+ dcmsr/libcmr/cid42.cc
+ dcmsr/libcmr/cid6147.cc
+ dcmsr/libcmr/cid7021.cc
+ dcmsr/libcmr/cid7181.cc
+ dcmsr/libcmr/cid7445.cc
+ dcmsr/libcmr/cid7452.cc
+ dcmsr/libcmr/cid7453.cc
+ dcmsr/libcmr/cid7464.cc
+ dcmsr/libcmr/cid7469.cc
+ dcmsr/libcmr/cid7551.cc
+
+- Updated code definitions for DICOM 2025e:
+ Updated automatically generated code definitions for coding schemes
+ "DCM", "NCIt" and "UMLS" based on the latest release of the DICOM
+ standard.
+ Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h
+ dcmsr/include/dcmtk/dcmsr/codes/ncit.h
+ dcmsr/include/dcmtk/dcmsr/codes/umls.h
+
+- Updated data dictionary for DICOM 2025e:
+ Updated data dictionary for the latest release of the DICOM standard,
+ although there were no changes (compared to the previous release).
+ Affects: dcmdata/data/dicom.dic
+ dcmdata/include/dcmtk/dcmdata/dcdeftag.h
+ dcmdata/libsrc/dcdictbi.cc
+
+**** Changes from 2025.11.17 (riesmeier)
+
+- Made use of getDestinationEncoding():
+ Call getDestinationEncoding() method instead of using the member
+ variable DestinationEncoding directly. This allows for overwriting
+ the destination encoding in a derived class.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the
+ proposal and use case.
+ Affects: dcmdata/libsrc/dcspchrs.cc
+
+**** Changes from 2025.11.15 (eichelberg)
+
+- Fixed minor warning on C++20 build.
+ Affects: dcmnet/apps/storescp.cc
+
+**** Changes from 2025.11.14 (eichelberg)
+
+- Added storescp option --max-associations:
+ Added a new command line option --max-associations to storescp that allows
+ the user to limit the number of network associations handled in parallel
+ when storescp is running in --fork mode. When the maximum number of child
+ processes is running, further incoming requests are kept on the listen
+ backlog until either a child process has ended or the request times out.
+ On Posix systems, this function uses the SIGCHLD signal to keep track of
+ child processes. On Windows, a list of child processes together with
+ RegisterWaitForSingleObject() is used instead.
+ Affects: dcmnet/apps/storescp.cc
+ dcmnet/docs/storescp.man
+
+**** Changes from 2025.11.13 (eichelberg)
+
+- Added callback parameter to "request fork" function:
+ Added an optional callback function pointer as a parameter to
+ DUL_requestForkOnTransportConnectionReceipt(). The callback will
+ only be used on Windows and on that platform will pass a handle
+ to the child process that has been created in the network module
+ to serve the incoming network assocation. The handle can be
+ used to maintain a list and count of active child processes
+ on Windows, where no SIGCHLD signal is available that automatically
+ notifies the parent process when a child process has ended.
+ Affects: dcmnet/include/dcmtk/dcmnet/dul.h
+ dcmnet/libsrc/dul.cc
+
+**** Changes from 2025.11.07 (eichelberg)
+
+- Fixed man page on Windows.
+ Affects: dcmdata/docs/img2dcm.man
+
+- Fixed man page on Windows.
+ Affects: dcmdata/docs/dcm2json.man
+
+**** Changes from 2025.11.03 (riesmeier)
+
+- Moved new regression tests to another file.
+ Affects: dcmdata/tests/tchval.cc
+ dcmdata/tests/tests.cc
+ dcmdata/tests/tvrdatim.cc
+
+- Fixed issue with VR scanner for "DateTime" values:
+ Fixed an issue with the VR scanner for an incorrect definition of
+ "DateTime" (DT) values: The UTC suffix "+0000" was not supported,
+ which was quite surprising since this is the current timezone for
+ for the UK, for example.
+ Also added a new regression test to check whether the VR scanner
+ correctly accepts and rejects certain timezones for DT values.
+ Thanks to Jez Cooke <jez.cooke@hamamatsu.eu> and Kade Rashid
+ <kade.rashid@hamamatsu.eu> for the report and suggested fix.
+ Affects: dcmdata/libsrc/vrscanl.c
+ dcmdata/libsrc/vrscanl.l
+ dcmdata/tests/tests.cc
+ dcmdata/tests/tvrdatim.cc
+
+- Fixed source code formatting.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcvrae.h
+ dcmnet/apps/dcmrecv.cc
+ dcmnet/apps/movescu.cc
+ dcmnet/apps/storescp.cc
+ dcmnet/docs/dcmrecv.man
+ dcmqrdb/apps/dcmqrscp.cc
+ dcmwlm/apps/wlcefs.cc
+
+**** Changes from 2025.11.02 (eichelberg)
+
+- Added IPv6 support to DCMTK's association acceptors:
+ Added support for explicitly selecting the IP protocol version (including
+ IPv6 and a dual-stack IPv4/v6 mode) to all DCMTK "server" applications
+ that accept incoming DICOM associations.
+ Thanks to Sobhita Mercy <sobhitamercy@gmail.com> for this contribution.
+ This closes GitHub pull request #128.
+ Affects: dcmnet/apps/dcmrecv.cc
+ dcmnet/apps/movescu.cc
+ dcmnet/apps/storescp.cc
+ dcmnet/docs/dcmrecv.man
+ dcmnet/docs/movescu.man
+ dcmnet/docs/storescp.man
+ dcmnet/include/dcmtk/dcmnet/dul.h
+ dcmnet/libsrc/dul.cc
+ dcmpstat/apps/dcmprscp.cc
+ dcmpstat/apps/dcmpsrcv.cc
+ dcmpstat/etc/dcmpstat.cfg
+ dcmpstat/include/dcmtk/dcmpstat/dviface.h
+ dcmpstat/include/dcmtk/dcmpstat/dvpscf.h
+ dcmpstat/libsrc/dviface.cc
+ dcmpstat/libsrc/dvpscf.cc
+ dcmqrdb/apps/dcmqrscp.cc
+ dcmqrdb/docs/dcmqrscp.man
+ dcmqrdb/libsrc/dcmqrcbm.cc
+ dcmwlm/apps/wlcefs.cc
+ dcmwlm/docs/wlmscpfs.man
+
+**** Changes from 2025.10.31 (eichelberg)
+
+- Added missing includes.
+ Affects: dcmdata/libsrc/dcdocdec.cc
+
+**** Changes from 2025.10.30 (eichelberg)
+
+- Switch stdout to binary on Windows:
+ Switch stdout to binary mode on Windows when decapsulating
+ an encapsulated document to stdout, to prevent CR/LF conversion.
+ Affects: dcmdata/libsrc/dcdocdec.cc
+
+**** Changes from 2025.10.29 (eichelberg)
+
+- Fixed minor warnings.
+ Affects: dcmdata/libsrc/dcjsonrd.cc
+
+**** Changes from 2025.10.28 (eichelberg)
+
+- DcmJSONReader::clear() now prevents double delete:
+ DcmJSONReader::clear() now sets jsonDataset_ and tokenArray_ to NULL after
+ deletion to prevent double-delete when the object is reused.
+ Thanks to GitHub user "Oss-Auditor" for the pull request.
+ This closes GitHub PR #131.
+ Affects: dcmdata/libsrc/dcjsonrd.cc
+
+**** Changes from 2025.10.25 (riesmeier)
+
+- Fixed issues with new command line tool dcmdecap.
+ Affects: dcmdata/apps/Makefile.in
+
+- Added new tools dcmdecap and dcmencap.
+ Affects: .gitignore
+
+**** Changes from 2025.10.25 (eichelberg)
+
+- Fix TCP initialization error message:
+ This fixes the following misleading error message that is printed
+ on Windows when connect() or select() fails:
+ "TCP Initialization Error: No error".
+ Thanks to Github user "luk1337" for the pull request
+ This closes Github pull request #129.
+ Affects: dcmnet/libsrc/dulfsm.cc
+
+- Added dcmdecap and dcmencap to module documentation.
+ Affects: dcmdata/docs/dcmdata.dox
+
+- Added new tool dcmdecap that extracts encapsulated documents:
+ Added new tool dcmencap that extracts encapsulated documents into
+ separate files. The formerly separate tools dcm2pdf and dcm2cda are
+ now deprecated and act as stubs that call dcmdecap.
+ Added: dcmdata/apps/dcmdecap.cc
+ dcmdata/docs/dcmdecap.man
+ dcmdata/include/dcmtk/dcmdata/dcdocdec.h
+ dcmdata/libsrc/dcdocdec.cc
+ Affects: dcmdata/apps/CMakeLists.txt
+ dcmdata/apps/Makefile.in
+ dcmdata/apps/dcm2cda.cc
+ dcmdata/apps/dcm2pdf.cc
+ dcmdata/docs/dcm2cda.man
+ dcmdata/docs/dcm2pdf.man
+ dcmdata/include/dcmtk/dcmdata/dcerror.h
+ dcmdata/libsrc/CMakeLists.txt
+ dcmdata/libsrc/Makefile.in
+ dcmdata/libsrc/dcerror.cc
+
+**** Changes from 2025.10.24 (eichelberg)
+
+- Fixed dcmAcceptOddAttributeLength implementation:
+ The global dcmdata setting 'dcmAcceptOddAttributeLength' determines how
+ illegal data elements with odd length are handled when reading.
+ By default, DCMTK accepts odd-length elements and silently pads
+ them to even length. If this setting is set to false, DCMTK instead
+ assumes that the attribute value is in fact even length and that
+ only the value of the length field is wrong, and increases the
+ length field by 1. This behaviour, which is not the default,
+ did not work correctly for elements larger than 4 kBytes, which are
+ skipped when reading from file and only loaded on demand later.
+ This has now been fixed.
+ Affects: dcmdata/libsrc/dcelem.cc
+
+**** Changes from 2025.10.17 (riesmeier)
+
+- Made DcmItem::updateSpecificCharacterSet() public:
+ The DcmItem::updateSpecificCharacterSet() method has been made public,
+ so that it can be called directly if needed (which is only true in
+ special use cases).
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the
+ original report.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h
+ dcmdata/include/dcmtk/dcmdata/dcspchrs.h
+
+**** Changes from 2025.10.16 (riesmeier)
+
+- Made sure not to use incompatible options:
+ Made sure that the options --ignore-mlut-depth and --ignore-vlut-depth
+ are not used together with --check-lut-depth, as they are mutually
+ exclusive.
+ Affects: dcmapps/include/dcmtk/dcmapps/dcm2img.h
+
+- Removed last (empty) entry from UID name map:
+ Removed the last (empty) entry from the central UID name mapping array
+ because it serves no purpose.
+ Thanks to DCMTK forum user "Shaeto" for the original report.
+ Affects: dcmdata/libsrc/dcuid.cc
+
+- Warn if Photometric Interpretation is missing:
+ Just warn if Photometric Interpretation is missing, when ACR-NEMA
+ compatibility is enabled.
+ Affects: dcmimgle/libsrc/didocu.cc
+
+**** Changes from 2025.10.07 (riesmeier)
+
+- Updated code definitions for DICOM 2025d:
+ Updated automatically generated code definitions for coding scheme "DCM".
+ For the coding schemes "NCIt" and "UMLS", there were no changes.
+ Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h
+ dcmsr/include/dcmtk/dcmsr/codes/ncit.h
+ dcmsr/include/dcmtk/dcmsr/codes/umls.h
+
+- Updated data dictionary for DICOM 2025d:
+ Updated data dictionary for the latest edition of the DICOM standard.
+ Affects: dcmdata/data/dicom.dic
+ dcmdata/include/dcmtk/dcmdata/dcdeftag.h
+ dcmdata/libsrc/dcdictbi.cc
+
+**** Changes from 2025.09.25 (eichelberg)
+
+- Fixed minor warning.
+ Affects: dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbm.h
+
+**** Changes from 2025.09.24 (eichelberg)
+
+- Enabled the use of TLS for sub-associations:
+ Enabled the use of TLS for storage sub-associations in dcmqrscp,
+ which completes the TLS support for the C-MOVE retrieve service.
+ Thanks to Nikolai Beck (GitHub user nbeck-SMT) for the pull request.
+ This closes GitHub PR #127.
+ Affects: dcmqrdb/include/dcmtk/dcmqrdb/dcmqrcbm.h
+ dcmqrdb/libsrc/dcmqrcbm.cc
+ dcmqrdb/libsrc/dcmqrsrv.cc
+
+- Added JPEG decoder option for preserving BitsStored:
+ Added a codec parameter and corresponing command line options in dcmdjpeg
+ and dcm2img that allow the value of Bits Stored to be preserved even if
+ the value in the JPEG bitstream is smaller than the value in the DICOM header.
+ This may help with correctly decoding some defective DICOM images.
+ This closes DCMTK issue #1054.
+ Affects: dcmapps/docs/dcm2img.man
+ dcmapps/include/dcmtk/dcmapps/dcm2img.h
+ dcmjpeg/apps/dcmdjpeg.cc
+ dcmjpeg/docs/dcmdjpeg.man
+ dcmjpeg/include/dcmtk/dcmjpeg/djcparam.h
+ dcmjpeg/include/dcmtk/dcmjpeg/djdecode.h
+ dcmjpeg/libsrc/djcodecd.cc
+ dcmjpeg/libsrc/djcparam.cc
+ dcmjpeg/libsrc/djdecode.cc
+
+**** Changes from 2025.09.19 (eichelberg)
+
+- Fixed off-by-one buffer overrun.
+ Affects: dcmdata/libsrc/dcencdoc.cc
+
+**** Changes from 2025.09.18 (eichelberg)
+
+- Fixed inconsistencies in command line options.
+ Affects: dcmdata/docs/dcmencap.man
+ dcmdata/libsrc/dcencdoc.cc
+
+- Fixed minor warnings.
+ Affects: dcmdata/libsrc/dcencdoc.cc
+ ofstd/libsrc/ofstub.cc
+
+**** Changes from 2025.09.17 (eichelberg)
+
+- Updated man pages for deprecated tools.
+ Affects: dcmdata/docs/cda2dcm.man
+ dcmdata/docs/pdf2dcm.man
+ dcmdata/docs/stl2dcm.man
+
+- Made depreciation warnings more prominent.
+ Affects: ofstd/libsrc/ofstub.cc
+
+**** Changes from 2025.09.17 (onken)
+
+- Fix reusability of SCP threads in pool:
+ Added more debug messages. Fixed some typos in TLS pool test case and
+ classes and make use OFStandard instead of custom methods.
+ Affects: dcmnet/include/dcmtk/dcmnet/scppool.h
+ dcmnet/include/dcmtk/dcmnet/scpthrd.h
+ dcmnet/libsrc/scppool.cc
+ dcmnet/libsrc/scpthrd.cc
+ dcmtls/tests/tscuscptls.cc
+
+**** Changes from 2025.09.17 (eichelberg)
+
+- Minor improvements for dcmencap:
+ The command line options for device data can now also be used when
+ encapsulating PDF and CDA documents, where the corresponding attributes
+ are optional. Also improved some warning/error messages.
+ Affects: dcmdata/docs/dcmencap.man
+ dcmdata/libsrc/dcencdoc.cc
+
+- Added consistency check for --series-from option:
+ Added consistency check for dcmencap's --series-from option to make sure
+ that series with different Modality values do not get merged.
+ Furthermore, fixed an inconsistency in the man page.
+ Affects: dcmdata/docs/dcmencap.man
+ dcmdata/include/dcmtk/dcmdata/dcencdoc.h
+ dcmdata/libsrc/dcencdoc.cc
+
+- Added new tool dcmencap that encapsulates documents:
+ Added new tool dcmencap that encapsulates documents of all types currently
+ supported in DICOM (PDF, CDA, STL, MTL and OBJ) into their corresponding
+ Encapulated Document Storage SOP Class in DICOM. The formerly separate tools
+ pdf2dcm, cda2dcm and stl2dcm are now deprecated and act as stubs that call
+ dcmencap. The document format (and, thus, SOP class) is now automatically
+ determined by default.
+ Added: dcmdata/apps/dcmencap.cc
+ dcmdata/docs/dcmencap.man
+ Affects: dcmdata/apps/CMakeLists.txt
+ dcmdata/apps/Makefile.dep
+ dcmdata/apps/Makefile.in
+ dcmdata/apps/cda2dcm.cc
+ dcmdata/apps/pdf2dcm.cc
+ dcmdata/apps/stl2dcm.cc
+ dcmdata/include/dcmtk/dcmdata/dcencdoc.h
+ dcmdata/libsrc/dcencdoc.cc
+
+**** Changes from 2025.09.15 (onken)
+
+- Fixed leak in SCP Pool class, re-use threads:
+ In the old implementation busy worker threads have been joined but not
+ deleted or re-used.
+ The updated implementation re-uses busy workers by putting them back
+ into the pool of idle threads. All threads (if ever busy or not) are now
+ joined and deleted when the pool is being destroyed.
+ The test has been expanded to use a more thread-safe approach on result
+ variables and to also tests thread-reuse for threads that had been put
+ back into the idle pool before.
+ Thanks to Chuang Zhao <zhaocccchuang@163.com> for the report and
+ analysis.
+ Affects: dcmnet/libsrc/scppool.cc
+ dcmnet/tests/tpool.cc
+
+**** Changes from 2025.09.10 (riesmeier)
+
+- Fixed typo in comment:
+ Thanks to GitHub user "mrbean-bremen" for the report (see PR #124).
+ Affects: .github/workflows/cmake-win.yml
+
+**** Changes from 2025.09.08 (riesmeier)
+
+- Added check of "writeMode" to write() method:
+ Added check of "writeMode" parameter to DcmFileFormat::write() method,
+ so that only a dataset (without meta header) is written if its value
+ is EWM_dataset, i.e. if requested by the caller. This behavior is now
+ consistent with the DcmFileFormat::saveFile() method.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the
+ original report on this issue.
+ Affects: dcmdata/libsrc/dcdatset.cc
+ dcmdata/libsrc/dcfilefo.cc
+
+**** Changes from 2025.09.03 (riesmeier)
+
+- Converted array index to unsigned integer value:
+ Converted array index to unsigned integer value to avoid warning message
+ reported by gcc 14 on Solaris, e.g. with -Wall or -Wchar-subscripts:
+ "warning: array subscript has type 'char'"
+ Also slightly restructured code to make it more readable.
+ Affects: dcmimage/include/dcmtk/dcmimage/diybrpxt.h
+
+**** Changes from 2025.08.29 (onken)
+
+- Replace old-style casts to avoid compiler warnings.
+ Affects: dcmiod/include/dcmtk/dcmiod/iodtypes.h
+ dcmiod/tests/tpalette.cc
+
+**** Changes from 2025.08.28 (onken)
+
+- Fix linker errors with dupl. method definitions.
+ Affects: dcmiod/include/dcmtk/dcmiod/iodtypes.h
+ dcmiod/libsrc/iodtypes.cc
+
+**** Changes from 2025.08.25 (onken)
+
+- Fix another data type size warning.
+ Affects: dcmfg/libsrc/fginterface.cc
+
+**** Changes from 2025.08.22 (eichelberg)
+
+- Set implementation information at runtime:
+ Added APIs that allow the user to set the Implementation Class UID and
+ Implementation Version name at runtime while writing a DICOM file,
+ processing an incoming network association request or configuring
+ and outgoing network association request.
+ Thanks to Vasyl Horbatenko (GitHub user doskachok) for the pull request.
+ This closes GitHub PR #68 and #69.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcfilefo.h
+ dcmdata/libsrc/dcfilefo.cc
+ dcmnet/include/dcmtk/dcmnet/assoc.h
+ dcmnet/include/dcmtk/dcmnet/scpcfg.h
+ dcmnet/include/dcmtk/dcmnet/scu.h
+ dcmnet/libsrc/assoc.cc
+ dcmnet/libsrc/scp.cc
+ dcmnet/libsrc/scpcfg.cc
+ dcmnet/libsrc/scppool.cc
+ dcmnet/libsrc/scu.cc
+
+**** Changes from 2025.08.22 (riesmeier)
+
+- Slightly enhanced new functionality of LUT class:
+ Slightly enhanced new functionality of the LUT class and fixed some
+ issues introduced with a recent commit (71567ae84).
+ Affects: dcmimgle/include/dcmtk/dcmimgle/diluptab.h
+ dcmimgle/libsrc/diluptab.cc
+
+**** Changes from 2025.08.22 (onken)
+
+- Remove superfluous comment line.
+ Affects: .gitignore
+
+- Restore old GitHub actions rules.
+ Affects: .github/workflows/cmake-win.yml
+
+- Use space between template angle brackets.
+ Affects: dcmfg/include/dcmtk/dcmfg/fginterface.h
+ dcmfg/libsrc/fginterface.cc
+ dcmseg/include/dcmtk/dcmseg/segdoc.h
+
+- Remove test app.
+ Affects: dcmseg/CMakeLists.txt
+ Removed: dcmseg/apps/CMakeLists.txt
+ dcmseg/apps/check_segs.md
+ dcmseg/apps/check_segs.sh
+ dcmseg/apps/segdigest.cc
+
+**** Changes from 2025.08.21 (onken)
+
+- Fix debug output.
+ Affects: dcmiod/include/dcmtk/dcmiod/iodtypes.h
+
+- Remove override specificier:
+ Marking methods with "override" is only perrmitted
+ in C+11 or later.
+ Affects: dcmect/include/dcmtk/dcmect/enhanced_ct.h
+ dcmfg/include/dcmtk/dcmfg/fginterface.h
+ dcmiod/include/dcmtk/dcmiod/iodimage.h
+ dcmpmap/include/dcmtk/dcmpmap/dpmparametricmapiod.h
+ dcmseg/include/dcmtk/dcmseg/segdoc.h
+
+- Fix some compiler warnings.
+ Affects: dcmfg/include/dcmtk/dcmfg/fginterface.h
+ dcmfg/libsrc/fginterface.cc
+ dcmseg/include/dcmtk/dcmseg/segutils.h
+
+- Added Labelmap Segmentation Support:
+ Added support for creating, writing and reading Labelmap Segmentation
+ Storage objects to the DCMTK dcmseg module. This also requires an update
+ of the underlying DCMTK dcmfg (functional group) and dcmiod (common iod
+ support) modules (libraries), e.g. to add new DICOM modules (such as the
+ Palette Color Lookup Table module) and to generalize pixel data handling
+ to support 16 bit pixel data in segmentations. This also led to updates
+ in related "higher" DCMTK modules like such as dcmect.
+ Furthermore, reading and writing segmentation objects now can make use
+ of threads in order to write the per-frame functional group information
+ which can lead to large performance gains in case the object contains
+ thousands of frames. The feature has been built into the dcmfg module
+ and by default, is turned off (i.e. only a single thread is used). One
+ reason is that DCMTK does not support the C++ "<thread>" API and thus
+ cannot determine the number of available CPU cores on its own. Thus, the
+ user has to enable the feature when using the dcmfg (FGInterface) or
+ more for segmentations, the DcmSegmentation API. Other objects like the
+ Enhanced CT objects within DCMTK's dcmect module can also make use the
+ the threaded API, but the related dcmfg feature is not yet exposed to
+ their public APIs. To see how the threaded approach can be used, look at
+ dcmseg/tests/tbigdim.cc which reads and writes per-frame functional
+ groups using 16 threads (without checking the available cores of the
+ system).
+ Furthermore, a few bugs have been fixed, and minor enhancements have
+ been added.
+ Added: dcmiod/include/dcmtk/dcmiod/modiccprofile.h
+ dcmiod/include/dcmtk/dcmiod/modpalettecolorlut.h
+ dcmiod/libsrc/modiccprofile.cc
+ dcmiod/libsrc/modpalettecolorlut.cc
+ dcmiod/tests/ticcprofile.cc
+ dcmiod/tests/tpalette.cc
+ dcmseg/apps/CMakeLists.txt
+ dcmseg/apps/check_segs.md
+ dcmseg/apps/check_segs.sh
+ dcmseg/apps/segdigest.cc
+ dcmseg/tests/tlabelmap.cc
+ dcmseg/tests/tpacking.cc
+ ofstd/include/dcmtk/ofstd/diag/vsconstexp.def
+ Affects: .github/workflows/cmake-win.yml
+ .gitignore
+ ANNOUNCE
+ CMake/GenerateDCMTKConfigure.cmake
+ Makefile
+ config/modules
+ dcmdata/apps/Makefile.dep
+ dcmdata/apps/cda2dcm.cc
+ dcmdata/libdcxml/Makefile.dep
+ dcmdata/libi2d/Makefile.dep
+ dcmdata/libsrc/Makefile.dep
+ dcmdata/tests/Makefile.dep
+ dcmect/include/dcmtk/dcmect/enhanced_ct.h
+ dcmect/libsrc/enhanced_ct.cc
+ dcmect/tests/t_huge_concat.cc
+ dcmfg/include/dcmtk/dcmfg/concatenationcreator.h
+ dcmfg/include/dcmtk/dcmfg/concatenationloader.h
+ dcmfg/include/dcmtk/dcmfg/fg.h
+ dcmfg/include/dcmtk/dcmfg/fgderimg.h
+ dcmfg/include/dcmtk/dcmfg/fginterface.h
+ dcmfg/include/dcmtk/dcmfg/fgseg.h
+ dcmfg/include/dcmtk/dcmfg/fgtypes.h
+ dcmfg/libsrc/Makefile.dep
+ dcmfg/libsrc/concatenationcreator.cc
+ dcmfg/libsrc/concatenationloader.cc
+ dcmfg/libsrc/fg.cc
+ dcmfg/libsrc/fgderimg.cc
+ dcmfg/libsrc/fginterface.cc
+ dcmfg/libsrc/fgseg.cc
+ dcmfg/libsrc/fgtypes.cc
+ dcmfg/tests/Makefile.dep
+ dcmfg/tests/t_concatenation_loader.cc
+ dcmimage/libsrc/Makefile.dep
+ dcmimgle/include/dcmtk/dcmimgle/diluptab.h
+ dcmimgle/libsrc/Makefile.dep
+ dcmimgle/libsrc/diluptab.cc
+ dcmiod/include/dcmtk/dcmiod/iodimage.h
+ dcmiod/include/dcmtk/dcmiod/iodtypes.h
+ dcmiod/include/dcmtk/dcmiod/iodutil.h
+ dcmiod/include/dcmtk/dcmiod/modbase.h
+ dcmiod/include/dcmtk/dcmiod/modgeneralimage.h
+ dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h
+ dcmiod/libsrc/CMakeLists.txt
+ dcmiod/libsrc/Makefile.dep
+ dcmiod/libsrc/Makefile.in
+ dcmiod/libsrc/iodmacro.cc
+ dcmiod/libsrc/iodtypes.cc
+ dcmiod/libsrc/iodutil.cc
+ dcmiod/libsrc/modmultiframedimension.cc
+ dcmiod/tests/CMakeLists.txt
+ dcmiod/tests/Makefile.dep
+ dcmiod/tests/Makefile.in
+ dcmiod/tests/tchecks.cc
+ dcmiod/tests/tests.cc
+ dcmjpeg/libsrc/Makefile.dep
+ dcmnet/apps/Makefile.dep
+ dcmpmap/include/dcmtk/dcmpmap/dpmparametricmapiod.h
+ dcmpmap/libsrc/dpmparametricmapiod.cc
+ dcmpstat/apps/Makefile.dep
+ dcmpstat/libsrc/Makefile.dep
+ dcmseg/CMakeLists.txt
+ dcmseg/include/dcmtk/dcmseg/segdoc.h
+ dcmseg/include/dcmtk/dcmseg/segment.h
+ dcmseg/include/dcmtk/dcmseg/segtypes.h
+ dcmseg/include/dcmtk/dcmseg/segutils.h
+ dcmseg/libsrc/Makefile.dep
+ dcmseg/libsrc/segdoc.cc
+ dcmseg/libsrc/segment.cc
+ dcmseg/libsrc/segtypes.cc
+ dcmseg/libsrc/segutils.cc
+ dcmseg/tests/CMakeLists.txt
+ dcmseg/tests/Makefile.dep
+ dcmseg/tests/Makefile.in
+ dcmseg/tests/tbigdim.cc
+ dcmseg/tests/tconcat_binary.cc
+ dcmseg/tests/tests.cc
+ dcmseg/tests/troundtrip.cc
+ dcmseg/tests/tutils.cc
+ dcmsr/libsrc/Makefile.dep
+ dcmtls/libsrc/tlsfmacr.h
+ dcmtract/include/dcmtk/dcmtract/trctrackset.h
+ oficonv/libsrc/Makefile.dep
+ ofstd/include/dcmtk/ofstd/ofdiag.h
+ ofstd/libsrc/Makefile.dep
+ ofstd/tests/Makefile.dep
+
+**** Changes from 2025.08.21 (eichelberg)
+
+- Added method for accessing a DICOM file preamble:
+ Added a method that allows the user to access the file preamble after reading
+ a DICOM file.
+ This closes DCMTK issue #185.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcmetinf.h
+ dcmdata/libsrc/dcmetinf.cc
+
+**** Changes from 2025.08.19 (eichelberg)
+
+- Improved CMake code for static builds:
+ The variables containing the lists of additional libraries that need to be
+ linked when a certain static library is linked (such as
+ LIBPNG_EXTRA_LIBS_STATIC) are now also taken into account on Windows.
+ Furthermore, added some improvements for static builds on Debian Linux.
+ Thanks to Khang Trần <khangthk@gmail.com> for the pull request.
+ This closes DCMTK PR #104.
+ Affects: CMake/3rdparty.cmake
+ CMake/dcmtkPrepare.cmake
+
+- Fixed sample code:
+ Added proper null termination to string in sample program.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the pull request.
+ This closes GitHub PR #123.
+ Affects: oficonv/docs/oficonv.dox
+
+- Link libnsl and libsocket only when required:
+ DCMTK no longer unconditionally tests or links against `nsl` and `socket`.
+ These libraries are now only considered on pre-11.4 Solaris systems,
+ where functions such as `gethostbyname` were historically provided
+ outside libc. This avoids dependencies on libraries that may directly
+ or indirectly pull in a different OpenSSL version.
+ Thanks to Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
+ for the pull request.
+ This closes GitHub PR #125.
+ Affects: CMake/dcmtkPrepare.cmake
+
+**** Changes from 2025.08.19 (riesmeier)
+
+- Reduced number of warnings (gcc -Wconversion):
+ Reduced number of warnings reported by gcc with extra warning option
+ -Wconversion.
+ Affects: dcmimgle/include/dcmtk/dcmimgle/diinpxt.h
+
+**** Changes from 2025.08.18 (riesmeier)
+
+- Fixed warning reported by Visual Studio.
+ Affects: dcmimgle/include/dcmtk/dcmimgle/diinpxt.h
+
+- Fixed off-by-one error when processing an image:
+ Fixed an off-by-one error when processing an unusual encoding of a DICOM
+ image, e.g. with partial access to the pixel data. The internal handling
+ of the input pixel data with a certain combination of VR, Bits Allocated
+ and Bits Stored (see "case 2c") was missing the final pixel value (for
+ images with an odd number of bytes) in size and could, therefore, result
+ in an undefined behavior (incl. an out-of-bounds write to a memory block
+ on the heap).
+ Thanks to drak <dr4k.sec@gmail.com> for the report and sample file.
+ Affects: dcmimgle/include/dcmtk/dcmimgle/diinpxt.h
+
+- Fixed issue with commit 7ad81d69b:
+ Fixed an issue with recently committed changes that fix a problem with
+ invalid YBR_FULL images
+ Affects: dcmimage/include/dcmtk/dcmimage/diybrpxt.h
+
+**** Changes from 2025.08.18 (eichelberg)
+
+- Fixed metaheader generation in dcmodify and dcmconv:
+ The dcmodify and dcmconv tools incorrectly changed the MediaStorageSOPClassUID
+ and MediaStorageSOPInstanceUID in the DICOM meta-header when processing
+ DICOMDIR files. This was caused by the EWM_createNewMeta write mode,
+ which was introduced as the default behavior for DcmFileFormat::saveFile()
+ in DCMTK 3.6.6. This option deleted and re-created the entire meta-header
+ before writing the file. When the SOP Class UID and the SOP Instance UID
+ were not present in the main dataset, a private SOP class with a
+ newly generated SOP Instance UID were written. This is now fixed:
+ MediaStorageSOPClassUID and MediaStorageSOPInstanceUID are preserved
+ when not present in the main dataset.
+ Furthermore, dcmodify's "--no-meta-uid" command line option, which was
+ apparently broken since DCMTK 3.6.6, is now also fixed.
+ This closes DCMTK issue #1148.
+ Affects: dcmdata/apps/mdfdsman.cc
+ dcmdata/include/dcmtk/dcmdata/dctypes.h
+ dcmdata/libsrc/dcfilefo.cc
+
+- Added note on character set conversion:
+ Added a note in the API documentation pointing out that the character set
+ conversion code will not perform a thorough validation of the input strings,
+ i.e. characters that are permitted in the source character set but forbidden
+ in DICOM will be converted without warning or error.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h
+ dcmdata/include/dcmtk/dcmdata/dcspchrs.h
+
+**** Changes from 2025.08.15 (riesmeier)
+
+- Fixed issue with invalid "YBR_FULL" DICOM images:
+ Fixed an issue when processing an invalid DICOM image with a Photometric
+ Interpretation of "YBR_FULL" and a Planar Configuration of "1" where
+ the number of pixels stored does not match the expected number of pixels
+ (much too less). Now, the pixel data of such an image is not processed
+ at all, but an empty image (black pixels) is created instead. The user
+ is warned about this by an appropriate log message.
+ Thanks to Ding zhengzheng <xiaozheng.ding399@gmail.com> for the report
+ and the sample file (PoC).
+ Affects: dcmimage/include/dcmtk/dcmimage/dicopxt.h
+ dcmimage/include/dcmtk/dcmimage/diybrpxt.h
+ dcmimgle/libsrc/dcmimage.cc
+
+**** Changes from 2025.08.11 (eichelberg)
+
+- Improved documentation of initializeXfer() method.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcdatset.h
+
+- Initialize dataset transfer syntax when reading file:
+ Added code to initialize the transfer syntax of the dataset component
+ when reading a DICOM file (DcmFileFormat), in order to make sure that
+ the right transfer syntax will be reported even if the dataet is empty.
+ This closes DCMTK issue #1159.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcdatset.h
+ dcmdata/libsrc/dcdatset.cc
+ dcmdata/libsrc/dcfilefo.cc
+
+**** Changes from 2025.08.05 (eichelberg)
+
+- Moved pragma to separate include file:
+ Moved a pragma needed for compilation with gcc on MacOS
+ into a separate include file referenced by the macro
+ DCMTK_DIAGNOSTIC_IGNORE_CLANG_PRAGMAS_ON_GCC.
+ Added: ofstd/include/dcmtk/ofstd/diag/clangprg.def
+ Affects: dcmdata/include/dcmtk/dcmdata/dcmxml/xml2dcm.h
+ dcmdata/libdcxml/xml2dcm.cc
+ dcmsr/apps/xml2dsr.cc
+ dcmsr/include/dcmtk/dcmsr/dsrxmlc.h
+ ofstd/include/dcmtk/ofstd/ofdiag.h
+
+**** Changes from 2025.08.04 (eichelberg)
+
+- Added method for activating the list of ciphersuites:
+ Added a method for activating the list of ciphersuites defined through
+ DcmTLSSCU::setTLSProfile() and DcmTLSSCU::addCipherSuite(). Previously
+ this list was never actually activated.
+ Thanks to Ben Chen <Ben.Chen@intusurg.com> for the bug report and patch.
+ Affects: dcmtls/include/dcmtk/dcmtls/tlsscu.h
+ dcmtls/libsrc/tlsscu.cc
+
+**** Changes from 2025.08.03 (eichelberg)
+
+- Added missing include on Windows.
+ Affects: dcmdata/libsrc/dcjsonrd.cc
+
+**** Changes from 2025.08.02 (eichelberg)
+
+- Added support for file BulkDataURIs in json2dcm:
+ Added support for reading bulk data from files in the local filesystem
+ when converting a dataset in DICOM JSON encoding to a DICOM file.
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+ dcmdata/include/dcmtk/dcmdata/dcjsonrd.h
+ dcmdata/libsrc/dcjsonrd.cc
+
+**** Changes from 2025.07.31 (eichelberg)
+
+- Fixed OFStandard API documentation:
+ Removed reference to big endian byte order in Base64 encoder and
+ decoder methods in class OFStandard since this does not apply to DICOM.
+ Affects: ofstd/include/dcmtk/ofstd/ofstd.h
+
+**** Changes from 2025.07.24 (eichelberg)
+
+- Added error code for unsupported URI type.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcerror.h
+ dcmdata/libsrc/dcerror.cc
+
+- Added default for bulk data size in help output.
+ Affects: dcmdata/apps/dcm2json.cc
+ dcmdata/docs/dcm2json.man
+
+**** Changes from 2025.07.16 (riesmeier)
+
+- Updated Context Group classes for DICOM 2025c:
+ Updated automatically generated Context Group classes for the latest
+ edition of the DICOM standard. All supported classes were updated,
+ even though there were no changes to most of them.
+ Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid11.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid218.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid244.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid247.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid29.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid42.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7551.h
+ dcmsr/libcmr/cid100.cc
+ dcmsr/libcmr/cid10013.cc
+ dcmsr/libcmr/cid10033.cc
+ dcmsr/libcmr/cid11.cc
+ dcmsr/libcmr/cid218.cc
+ dcmsr/libcmr/cid244.cc
+ dcmsr/libcmr/cid247.cc
+ dcmsr/libcmr/cid29.cc
+ dcmsr/libcmr/cid4020.cc
+ dcmsr/libcmr/cid4021.cc
+ dcmsr/libcmr/cid4031.cc
+ dcmsr/libcmr/cid42.cc
+ dcmsr/libcmr/cid6147.cc
+ dcmsr/libcmr/cid7021.cc
+ dcmsr/libcmr/cid7181.cc
+ dcmsr/libcmr/cid7445.cc
+ dcmsr/libcmr/cid7452.cc
+ dcmsr/libcmr/cid7453.cc
+ dcmsr/libcmr/cid7464.cc
+ dcmsr/libcmr/cid7469.cc
+ dcmsr/libcmr/cid7551.cc
+
+- Updated code definitions for DICOM 2025c:
+ Updated automatically generated code definitions for coding schemes "DCM"
+ and "UMLS". For the coding scheme "NCIt", there were no changes.
+ Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h
+ dcmsr/include/dcmtk/dcmsr/codes/ncit.h
+ dcmsr/include/dcmtk/dcmsr/codes/umls.h
+
+- Updated data dictionary for DICOM 2025c:
+ Updated data dictionary for the latest edition of the DICOM standard,
+ which has been released only recently.
+ Affects: dcmdata/data/dicom.dic
+ dcmdata/include/dcmtk/dcmdata/dcdeftag.h
+ dcmdata/libsrc/dcdictbi.cc
+
+**** Changes from 2025.07.12 (riesmeier)
+
+- Replaced tab characters by spaces.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcjsonrd.h
+ dcmdata/libsrc/dcjsonrd.cc
+
+**** Changes from 2025.07.11 (eichelberg)
+
+- Refactored DICOM JSON parser into reusable class:
+ Refactored the DICOM JSON model parser that provides the core functionality
+ of the json2dcm application into a reusable class in the dcmdata library.
+ In this process, the code was also significantly revised and refined.
+ Added: dcmdata/include/dcmtk/dcmdata/dcjsonrd.h
+ dcmdata/libsrc/dcjsonrd.cc
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/libsrc/CMakeLists.txt
+ dcmdata/libsrc/Makefile.in
+
+**** Changes from 2025.07.10 (riesmeier)
+
+- Replaced wrong term in manpage.
+ Affects: dcmdata/docs/json2dcm.man
+
+- Fixed various spelling and formatting issues.
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+
+**** Changes from 2025.07.09 (eichelberg)
+
+- Fixed warnings from gcc on MacOS 15:
+ The version of libxml2 provided as part of the MacOS 15 development tools
+ contain some Clang specific pragmas that cause warnings when compiling
+ with gcc. These are now suppressed.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcmxml/xml2dcm.h
+ dcmdata/libdcxml/xml2dcm.cc
+ dcmsr/apps/xml2dsr.cc
+ dcmsr/include/dcmtk/dcmsr/dsrxmlc.h
+
+- Removed unneccessary parameter.
+ Affects: dcmdata/apps/json2dcm.cc
+
+**** Changes from 2025.07.08 (eichelberg)
+
+- Added options for handling JSON arrays of datasets:
+ Added command line options for handling JSON arrays of DICOM JSON datasets,
+ which are returned by DICOMweb services such as QIDO-RS or WADO-RS when
+ multiple datasets are returned for one request.
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+
+**** Changes from 2025.07.07 (eichelberg)
+
+- Added --ignore-bulkdata-uri option to json2dcm:
+ Added a command line option that allows json2dcm to ignore bulk data URIs
+ in DICOM JSON files, which are not yet supported. Furthermore revised the
+ logger messages for better consistency and less duplication.
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+
+- Improved json2dcm performance:
+ Improved json2dcm performance, in particular when reading large look-up
+ tables. Also improved consistency of logger output.
+ Affects: dcmdata/apps/json2dcm.cc
+
+**** Changes from 2025.07.01 (riesmeier)
+
+- Made some functions virtual to allow overriding:
+ Made some functions for character set conversion virtual to allow for
+ overriding them in derived classes.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the idea.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h
+ dcmdata/include/dcmtk/dcmdata/dcspchrs.h
+ dcmdata/libsrc/dcitem.cc
+
+- Do not warn on "Undefind Length" for some VRs:
+ Do not warn when using "Undefined Length" for VRs that support this
+ according to DICOM PS3.5, even if it does not occur in practice.
+ Affects: dcmdata/libsrc/dcitem.cc
+
+**** Changes from 2025.06.23 (riesmeier)
+
+- Fixed formatting and replaced wrong term.
+ Affects: dcmdata/docs/dcm2json.man
+
+**** Changes from 2025.06.23 (eichelberg)
+
+- Added note on bulk data export.
+ Affects: dcmdata/docs/dcm2json.man
+
+**** Changes from 2025.06.19 (riesmeier)
+
+- Fixed minor issues in manpage:
+ Fixed minor issues in manpage, e.g. capitalization, line breaks,
+ indentation and missing Doxygen markup.
+ Affects: dcmdata/docs/dcm2json.man
+ dcmdata/docs/json2dcm.man
+
+- Fixed indentation of source header.
+ Affects: dcmdata/apps/dcm2json.cc
+
+**** Changes from 2025.06.19 (eichelberg)
+
+- Added a note that json2dcm accepts trailing commas:
+ Added a note to the manual page explaining that json2dcm will accepts
+ some invalid JSON datasets, such as datasets with trailing commas,
+ without error or warning because they are gracefully handled by the
+ underlying JSON parser.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the report.
+ Affects: dcmdata/docs/json2dcm.man
+
+- Fixed generation of 32-bit BMP on Big Endian CPUs:
+ Fixed the conversion of DICOM images to 32-bit BMP files, which worked
+ correctly on Little Endian CPUs but not on Big Endian CPUs.
+ Affects: dcmimage/include/dcmtk/dcmimage/dicopxt.h
+ dcmimgle/libsrc/dimoimg.cc
+
+**** Changes from 2025.06.19 (malaterre)
+
+- Access JSON bulk data URI prefix through API:
+ In DcmJsonFormat::writeBulkData(), access the URI prefix for bulk data
+ URIs through the official API method getBulkDataURIPrefix() in order
+ to allow derived classes to override the implementation.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the pull request.
+ This closes GitHub PR #121.
+ Affects: dcmdata/libsrc/dcjson.cc
+
+- Reworked JSON writeBulkData API:
+ Now exposing the same set of parameters as the caller function
+ writeBinaryAttribute.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the pull request.
+ This closes GitHub PR #122.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcjson.h
+ dcmdata/libsrc/dcchrstr.cc
+ dcmdata/libsrc/dcelem.cc
+ dcmdata/libsrc/dcjson.cc
+ dcmdata/libsrc/dcpixel.cc
+ dcmdata/libsrc/dcvrds.cc
+ dcmdata/libsrc/dcvrfd.cc
+ dcmdata/libsrc/dcvrfl.cc
+ dcmdata/libsrc/dcvris.cc
+ dcmdata/libsrc/dcvrsv.cc
+ dcmdata/libsrc/dcvruv.cc
+
+**** Changes from 2025.06.16 (eichelberg)
+
+- Reworded comment on HP color transform:
+ Reworded comment about the non-standard HP color transformation in JPEG-LS.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the pull request.
+ This closes GitHub PR #119.
+ Affects: dcmjpls/libsrc/djcodece.cc
+
+**** Changes from 2025.06.14 (eichelberg)
+
+- Fixed minor MSVC warning.
+ Affects: dcmdata/apps/json2dcm.cc
+
+**** Changes from 2025.06.13 (xu)
+
+- Changes to JSON2DCM: Moved Exitcodes to JSON2DCM to ensure fixed codes. Removed some DEBUG testing output.
+ Affects: dcmdata/apps/json2dcm.cc
+
+**** Changes from 2025.06.13 (eichelberg)
+
+- Apply bit mask when passing pixel data to CharLS:
+ Apply bit mask when passing pixel data to the CharLS JPEG-LS encoder
+ in "cooked" mode.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the bug report.
+ This closes DCMTK Issue #1160.
+ Affects: dcmjpls/libsrc/djcodece.cc
+
+**** Changes from 2025.06.13 (onken)
+
+- Made destructor virtual:
+ Classes with virtual functions must have their destructor also made
+ virtual.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the pull
+ request.
+ This closes GitHub pull request #120.
+ Affects: dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h
+
+**** Changes from 2025.06.12 (riesmeier)
+
+- Minor fixes to manpage and syntax usage:
+ Made the description of the tool "json2dcm" more consistent with the
+ one of the pre-existing tool "xml2dcm".
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+
+- Changed log level and text of some log messages:
+ Changed log level of some log messages and slightly modified the text.
+ Also check the output file for an empty string (similar to "xml2dcm").
+ Affects: dcmdata/apps/json2dcm.cc
+
+- Various minor fixes, mainly related to json2dcm:
+ Various minor fixes that are mainly related to the new command line tool
+ json2dcm. For example, spelling errors, wrong capitalization, unused
+ error and exit codes. Also made the log output more consistent.
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+ dcmdata/include/dcmtk/dcmdata/dcerror.h
+ dcmdata/libsrc/dcchrstr.cc
+ dcmdata/libsrc/dcerror.cc
+ dcmdata/libsrc/dcistrmz.cc
+ dcmdata/libsrc/dcitem.cc
+ dcmdata/libsrc/dcpixel.cc
+ dcmdata/libsrc/dcrleccd.cc
+ dcmdata/libsrc/dcvrds.cc
+ dcmdata/libsrc/dcvris.cc
+
+**** Changes from 2025.06.10 (riesmeier)
+
+- Fixed wrong sub-group title.
+ Affects: dcmdata/docs/json2dcm.man
+
+**** Changes from 2025.06.10 (eichelberg)
+
+- Updated documentation parameter "dcmfile-out":
+ Updated documentation of command line parameter "dcmfile-out",
+ as writing to stdout is supported, but the paramters is not optional
+ anymore. Also fixed minor issues.
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+
+**** Changes from 2025.06.10 (riesmeier)
+
+- Added new command line tool "json2dcm".
+ Affects: .gitignore
+
+- Added "json2dcm" to module's documentation page.
+ Affects: dcmdata/docs/dcmdata.dox
+
+- Updated documentation of parameter "jsonfile-in":
+ Updated documentation of command line parameter "jsonfile-in" as reading
+ from stdin is now also supported. Also fixed various other minor issues
+ related to the documentation.
+ Affects: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+
+**** Changes from 2025.06.09 (eichelberg)
+
+- Added support for reading from stdin:
+ Added support in json2dcm for reading the JSON file from stdin if the
+ input file name is given as "-". Improved character set related warnings.
+ Affects: dcmdata/apps/json2dcm.cc
+
+**** Changes from 2025.06.07 (eichelberg)
+
+- Fixed memory leaks and segfault in json2dcm:
+ Fixed two memory leaks and a segmentation fault that could occur on some
+ platforms due to a loop reading past the end of an array.
+ Affects: dcmdata/apps/json2dcm.cc
+
+- Replaced C-style casts with C++ casts.
+ Affects: dcmdata/apps/json2dcm.cc
+
+- Fixed URL encoding of path separators.
+ Affects: dcmdata/apps/dcm2json.cc
+
+- Minor fix in jsmn API definition.
+ Affects: ofstd/include/dcmtk/ofstd/ofjsmn.h
+
+**** Changes from 2025.06.06 (eichelberg)
+
+- Fixed shared library build.
+ Affects: ofstd/include/dcmtk/ofstd/ofjsmn.h
+
+**** Changes from 2025.06.06 (xu)
+
+- Initial release of the json2dcm command line tool:
+ Initial release of json2dcm, a tool that converts the contents of a
+ DICOM dataset in JSON encoding to a binary DICOM file or dataset.
+ The JSON document is expected to conform to the "DICOM JSON Model"
+ as defined in DICOM Part 18, Section F. In this initial release,
+ attribute values referenced through BulkDataURIs are not yet supported.
+ Added: dcmdata/apps/json2dcm.cc
+ dcmdata/docs/json2dcm.man
+ Affects: dcmdata/apps/CMakeLists.txt
+ dcmdata/apps/Makefile.in
+ dcmdata/include/dcmtk/dcmdata/dcerror.h
+ dcmdata/libsrc/dcerror.cc
+
+- Added JSON parser to module ofstd:
+ Added the "jmsn" header-only JSON parser by Serge Zaitsev to module ofstd.
+ Added: ofstd/include/dcmtk/ofstd/ofjsmn.h
+ ofstd/libsrc/ofjsmn.cc
+ Affects: COPYRIGHT
+ ofstd/libsrc/CMakeLists.txt
+ ofstd/libsrc/Makefile.in
+
+**** Changes from 2025.06.06 (eichelberg)
+
+- Encode special characters in file: URLs.
+ Affects: dcmdata/apps/dcm2json.cc
+
+**** Changes from 2025.06.05 (riesmeier)
+
+- Enhanced log output for incorrect pixel data:
+ Enhanced log output for incorrectly encoded encapsulated pixel data.
+ In particular, when encapsulated pixel data is encoded with a VR of OW
+ instead of OB, the warning message is now much easier to understand.
+ Affects: dcmdata/libsrc/dcitem.cc
+
+- Made output of warning messages more consistent.
+ Affects: dcmdata/libsrc/dcitem.cc
+
+**** Changes from 2025.06.01 (onken)
+
+- Fixed test failing due to new ftoa implementation:
+ Some months ago DCMTK has introduced a new OFStandard::ftoa
+ implementation() which leads to slightly different floating
+ point numbers when converting from a strings.
+ Affects: dcmfg/tests/t_concatenation_loader.cc
+
+**** Changes from 2025.06.01 (eichelberg)
+
+- Fixed bug in dcm2json:
+ Fixed bug in dcm2json that caused the tool to crash when compiled with STL.
+ Affects: dcmdata/apps/dcm2json.cc
+
+**** Changes from 2025.05.30 (onken)
+
+- Make DCMTK clients build w/o __cplusplus setting:
+ For its internal C++ standard version testing DCMTK sets the __cplusplus
+ macro for Visual Studio since some versions don't set it.
+ However, some external projects that just include the result of this check
+ (which can be found in DCMTK "main" configuration header osconfig.h),
+ might build their code without this flag and fail if osconfig.h still
+ relies on it.
+ The current patch does not change DCMTK's internal version checking but
+ makes sure that once built external projects don't stumble over the
+ __cplusplus macro requirements in osconfig.h. Instead, osconfig.h now
+ checks for _MSVC_LANG (and __cplusplus if that cannot be found).
+ Thanks to Jean-Christophe Fillion-Robins who originally came up with the
+ patch in the the CommonTK (CTK) project.
+ Affects: CMake/osconfig.h.in
+
+**** Changes from 2025.05.28 (riesmeier)
+
+- Added missing GNU Autoconf support to "tests".
+ Affects: dcmtract/tests/Makefile.dep
+ dcmtract/tests/Makefile.in
+
+**** Changes from 2025.05.28 (eichelberg)
+
+- Fixed JSON conversion of compressed images.
+ Affects: dcmdata/libsrc/dcpixel.cc
+
+- Minor fixes in dcm2json.
+ Affects: dcmdata/apps/dcm2json.cc
+ dcmdata/libsrc/dcjson.cc
+
+**** Changes from 2025.05.28 (onken)
+
+- Fixed compiler error/warning in test.
+ Affects: dcmtract/tests/tcreate.cc
+
+**** Changes from 2025.05.27 (onken)
+
+- Fix writing of Tractography Results Series:
+ Fix writing of Tractography Results Series which has been omitted in
+ the past.
+ Also fixed requirement for Referenced Instance Sequence and added
+ debug messages.
+ Added test that demonstrates how to create an Tractography Results
+ object and is helpful to find problems with the code.
+ Thanks to forum user "hapap" for the report.
+ Added: dcmtract/tests/CMakeLists.txt
+ dcmtract/tests/tcreate.cc
+ dcmtract/tests/tests.cc
+ Affects: dcmtract/CMakeLists.txt
+ dcmtract/include/dcmtk/dcmtract/trctypes.h
+ dcmtract/libsrc/trcmodtractresults.cc
+ dcmtract/libsrc/trctrackset.cc
+ dcmtract/libsrc/trctractographyresults.cc
+ dcmtract/libsrc/trctypes.cc
+
+- Use temp filename.
+ Affects: dcmect/tests/t_overflow.cc
+
+- Added "component" to debug dump.
+ Affects: dcmiod/libsrc/iodrules.cc
+
+**** Changes from 2025.05.27 (eichelberg)
+
+- Fixed compilation of dcm2json on Windows.
+ Affects: dcmdata/apps/dcm2json.cc
+
+**** Changes from 2025.05.23 (eichelberg)
+
+- Added support for BulkDataURI in JSON export:
+ Added support for the generation of BulkDataURIs when exporting DICOM files
+ to JSON in the dcm2json tool. When enabled, bulk data is stored in files
+ that are expected to be accessible through a WADO-RS service. A user-defined
+ URI prefix can be specified for this purpose. Since dcm2json is not a complete
+ DICOMweb implementation, there is no support (yet) for generating MIME multipart
+ structures with bulk data references formatted as a UUID.
+ This closes DCMTK Feature #1151.
+ Affects: dcmdata/apps/dcm2json.cc
+ dcmdata/docs/dcm2json.man
+ dcmdata/include/dcmtk/dcmdata/dcerror.h
+ dcmdata/include/dcmtk/dcmdata/dcjson.h
+ dcmdata/include/dcmtk/dcmdata/dcpixseq.h
+ dcmdata/include/dcmtk/dcmdata/dcxfer.h
+ dcmdata/libsrc/dcchrstr.cc
+ dcmdata/libsrc/dcelem.cc
+ dcmdata/libsrc/dcerror.cc
+ dcmdata/libsrc/dcjson.cc
+ dcmdata/libsrc/dcpixel.cc
+ dcmdata/libsrc/dcpixseq.cc
+ dcmdata/libsrc/dcvrds.cc
+ dcmdata/libsrc/dcvrfd.cc
+ dcmdata/libsrc/dcvrfl.cc
+ dcmdata/libsrc/dcvris.cc
+ dcmdata/libsrc/dcvrobow.cc
+ dcmdata/libsrc/dcvrod.cc
+ dcmdata/libsrc/dcvrof.cc
+ dcmdata/libsrc/dcvrol.cc
+ dcmdata/libsrc/dcvrov.cc
+ dcmdata/libsrc/dcvrsv.cc
+ dcmdata/libsrc/dcvruv.cc
+ dcmdata/libsrc/dcxfer.cc
+
+**** Changes from 2025.05.14 (eichelberg)
+
+- Fixed linker warning on MacOS.
+ Affects: dcmnet/apps/CMakeLists.txt
+
+- Fixed C++98 build.
+ Affects: dcmdata/libsrc/dcvrobow.cc
+
+**** Changes from 2025.05.09 (eichelberg)
+
+- Added TLS support to movescu:
+ Added TLS support to the movescu tool, both for outgoing
+ and for incoming associations.
+ Affects: dcmnet/apps/CMakeLists.txt
+ dcmnet/apps/Makefile.in
+ dcmnet/apps/movescu.cc
+ dcmnet/docs/movescu.man
+ dcmnet/libsrc/dcmtrans.cc
+
+- Added TLS support for C-MOVE in dcmqrscp:
+ The version of dcmqrscp in DCMTK 3.6.9 had partial support for secure
+ connections in that TLS was supported for incoming associations,
+ but not for outgoing connections. This means that TLS worked for
+ storage, query and retrieve with C-GET, but not with C-MOVE. The
+ TLS support has now be completed to also cover the outgoing
+ associations required for C-MOVE.
+ Affects: dcmqrdb/apps/dcmqrscp.cc
+ dcmqrdb/include/dcmtk/dcmqrdb/dcmqropt.h
+ dcmqrdb/libsrc/dcmqrcbm.cc
+ dcmqrdb/libsrc/dcmqropt.cc
+
+**** Changes from 2025.05.08 (onken)
+
+- Handle NULL values appropriately:
+ The compare methods() in DcmOtherByteOtherWord and DcmPolymorphOBOW did
+ not properly check for NULL values before handing them into memcmp().
+ Affects: dcmdata/include/dcmtk/dcmdata/dcvrobow.h
+ dcmdata/libsrc/dcvrobow.cc
+ dcmdata/libsrc/dcvrpobw.cc
+
+**** Changes from 2025.04.16 (riesmeier)
+
+- Indicated retired attributes in documentation:
+ Made sure that the recently retired EthnicGroup attribute is documented
+ as such, both in header files and man pages.
+ Affects: dcmqrdb/docs/dcmqrscp.man
+ dcmwlm/docs/wlmscpfs.man
+ dcmwlm/include/dcmtk/dcmwlm/wlds.h
+
+- Added support for new DICONDE Storage SOP Class:
+ Added support for the DICONDE Storage SOP Class for ultrasonic waveforms
+ introduced with DICOM 2025b (based on a revised version of ASTM E2663).
+ Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h
+ dcmdata/libsrc/dcuid.cc
+ dcmnet/docs/movescu.man
+ dcmnet/docs/storescp.man
+ dcmnet/etc/storescp.cfg
+ dcmnet/etc/storescu.cfg
+ dcmqrdb/docs/dcmqrscp.man
+ dcmqrdb/etc/dcmqrprf.cfg
+
+- Updated Context Group classes for DICOM 2025b:
+ Updated automatically generated Context Group classes for the latest
+ edition of the DICOM standard. All supported classes were updated,
+ even though there were no changes to most of them.
+ Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid11.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid218.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid244.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid247.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid29.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid42.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7551.h
+ dcmsr/libcmr/cid100.cc
+ dcmsr/libcmr/cid10013.cc
+ dcmsr/libcmr/cid10033.cc
+ dcmsr/libcmr/cid11.cc
+ dcmsr/libcmr/cid218.cc
+ dcmsr/libcmr/cid244.cc
+ dcmsr/libcmr/cid247.cc
+ dcmsr/libcmr/cid29.cc
+ dcmsr/libcmr/cid4020.cc
+ dcmsr/libcmr/cid4021.cc
+ dcmsr/libcmr/cid4031.cc
+ dcmsr/libcmr/cid42.cc
+ dcmsr/libcmr/cid6147.cc
+ dcmsr/libcmr/cid7021.cc
+ dcmsr/libcmr/cid7181.cc
+ dcmsr/libcmr/cid7445.cc
+ dcmsr/libcmr/cid7452.cc
+ dcmsr/libcmr/cid7453.cc
+ dcmsr/libcmr/cid7464.cc
+ dcmsr/libcmr/cid7469.cc
+ dcmsr/libcmr/cid7551.cc
+
+- Updated code definitions for DICOM 2025b:
+ Updated automatically generated code definitions for coding schemes "DCM"
+ and "UMLS". For the coding scheme "NCIt", there were no changes.
+ Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h
+ dcmsr/include/dcmtk/dcmsr/codes/ncit.h
+ dcmsr/include/dcmtk/dcmsr/codes/umls.h
+
+- Updated data dictionary for DICOM 2025b:
+ Updated data dictionary for the latest edition of the DICOM standard, which
+ has been released only recently.
+ Since one of the DICOM attributes has been "retired", the name of the
+ associated DcmTagKey constant also changed. This required minor changes to
+ the source code of the dcmiod, dcmqrdb, dcmrt and dcmwlm module.
+ Affects: dcmdata/data/dicom.dic
+ dcmdata/include/dcmtk/dcmdata/dcdeftag.h
+ dcmdata/libsrc/dcdictbi.cc
+ dcmiod/libsrc/modhelp.cc
+ dcmqrdb/libsrc/dcmqrdbi.cc
+ dcmrt/libsrc/drtdose.cc
+ dcmrt/libsrc/drtimage.cc
+ dcmrt/libsrc/drtionpl.cc
+ dcmrt/libsrc/drtiontr.cc
+ dcmrt/libsrc/drtplan.cc
+ dcmrt/libsrc/drtstrct.cc
+ dcmrt/libsrc/drttreat.cc
+ dcmwlm/libsrc/wlds.cc
+
+**** Changes from 2025.04.08 (riesmeier)
+
+- Added note on the potential misuse of options:
+ Added a security note on the potential misuse of options/parameters
+ that can lead to an injection of dangerous content into the HTML/XHTML
+ output.
+ Thanks to drak <dr4k.sec@gmail.com> for the report and proof of concept.
+ Affects: dcmsr/docs/dsr2html.man
+ dcmsr/include/dcmtk/dcmsr/dsrcomvl.h
+ dcmsr/include/dcmtk/dcmsr/dsrdoc.h
+ dcmsr/include/dcmtk/dcmsr/dsrdoctn.h
+ dcmsr/include/dcmtk/dcmsr/dsrdoctr.h
+ dcmsr/include/dcmtk/dcmsr/dsrimgvl.h
+ dcmsr/include/dcmtk/dcmsr/dsrwavvl.h
+
+**** Changes from 2025.04.05 (riesmeier)
+
+- Updated list of multi-frame Storage SOP Classes:
+ Updated the list of multi-frame Storage SOP Classes that is used when
+ generating a DICOMDIR based on an Application Profile that supports
+ MPEG compression.
+ Affects: dcmdata/libsrc/dcddirif.cc
+
+- Added support for new Directory Record Type:
+ Added support for new Waveform Presentation State Directory Record Type
+ "WF PRESENTATION" introduced with Supplement 236, i.e. to the DICOMDIR
+ creating, reading and writing code.
+ This finally closes DCMTK Conformance #1152.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcddirif.h
+ dcmdata/include/dcmtk/dcmdata/dcdirrec.h
+ dcmdata/libsrc/dcddirif.cc
+ dcmdata/libsrc/dcdirrec.cc
+
+**** Changes from 2025.03.24 (eichelberg)
+
+- Disable Borland workarounds when using bcc64x:
+ The Embarcadero bcc64x compiler, a Clang-based 64-bit compiler, does not
+ require or support the workarounds in the DCMTK code implemented once for
+ Borland 5.5. These workarounds are now disabled if bcc64x is detected.
+ Thanks to DCMTK forum user "OliWe" for the suggestion.
+ Affects: CMake/osconfig.h.in
+ dcmdata/libsrc/dcdict.cc
+ oflog/include/dcmtk/oflog/config/win32.h
+ oflog/libsrc/fileap.cc
+ oflog/libsrc/timehelp.cc
+ ofstd/libsrc/ofconsol.cc
+ ofstd/libsrc/ofxml.cc
+
+**** Changes from 2025.03.22 (riesmeier)
+
+- Added quotation marks to CMake variables.
+ Affects: INSTALL
+
+**** Changes from 2025.03.21 (eichelberg)
+
+- Improved description of support lib compile flags:
+ Improved the description of the runtime library selection flags required
+ when compiling the support libraries on Windows.
+ Thanks to DCMTK forum user "pierrechatelier" for the suggestion.
+ Affects: INSTALL
+
+**** Changes from 2025.03.14 (riesmeier)
+
+- Added support for new Presentation States:
+ Added support for new Presentation State SOP Classes introduced with
+ Supplement 236 (Waveform Presentation State) to the DICOM SR module.
+ Affects: dcmsr/include/dcmtk/dcmsr/dsrtypes.h
+ dcmsr/libsrc/dsrtypes.cc
+
+- Added support for new Storage SOP Classes:
+ Added definition of new Storage SOP Class UIDs introduced with Supplement
+ 236 (Waveform Presentation State). Also added support for these Storage
+ SOP Classes to the various networking tools.
+ This partly closes DCMTK Conformance #1152.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h
+ dcmdata/libsrc/dcuid.cc
+ dcmnet/docs/getscu.man
+ dcmnet/docs/movescu.man
+ dcmnet/docs/storescp.man
+ dcmnet/etc/storescp.cfg
+ dcmnet/etc/storescu.cfg
+ dcmqrdb/docs/dcmqrscp.man
+ dcmqrdb/etc/dcmqrprf.cfg
+
+**** Changes from 2025.03.14 (onken)
+
+- Don't check for libsndfile in default build:
+ The public DCMTK does not make any use of libsndfile; therefore there
+ is no need to check for the library at all.
+ For CMake, the library is not checked unless DCMTK_WITH_SNDFILE is
+ enabled by the user.
+ For autoconf, the presence of libsndfile is only checked if
+ configured with --with-libsndfile. Only if found the script will
+ print "checking whether to include libsndfile support...yes" and in
+ all other cases will (default, --without-libsndfile, --with-libsndfile
+ but library not found) print "no" instead.
+ Affects: CMake/dcmtkPrepare.cmake
+ config/configure
+ config/configure.in
+
+**** Changes from 2025.03.08 (eichelberg)
+
+- Removed unused variable.
+ Affects: dcmnet/libsrc/dulfsm.cc
+
+**** Changes from 2025.03.07 (eichelberg)
+
+- Fixed error message on Windows.
+ Affects: dcmnet/libsrc/dulfsm.cc
+
+**** Changes from 2025.03.06 (riesmeier)
+
+- Added initial support for new transfer syntax:
+ Added initial support for the Deflated Image Frame Compression Transfer
+ Syntax that was introduced with Supplement 244.
+ The current support includes reading and writing of DICOM files and
+ data sets that are encoded with this new transfer syntax as well as
+ basic network support (including some of the command line tools).
+ What is still missing is the compression and decompression of this
+ transfer syntax, i.e. the lossless transcoding to/from the various
+ uncompressed transfer syntaxes.
+ This closes DCMTK Conformance #1149.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcuid.h
+ dcmdata/include/dcmtk/dcmdata/dcxfer.h
+ dcmdata/libsrc/dcuid.cc
+ dcmdata/libsrc/dcxfer.cc
+ dcmnet/apps/echoscu.cc
+ dcmnet/apps/movescu.cc
+ dcmnet/apps/storescp.cc
+ dcmnet/docs/echoscu.man
+ dcmnet/docs/movescu.man
+ dcmnet/docs/storescp.man
+ dcmnet/etc/storescp.cfg
+ dcmnet/etc/storescu.cfg
+ dcmnet/libsrc/dimse.cc
+ dcmqrdb/etc/dcmqrprf.cfg
+
+**** Changes from 2025.03.04 (riesmeier)
+
+- Use non-throwing new operator:
+ Use a non-throwing new operator when allocating huge amounts of memory.
+ Affects: dcmimage/include/dcmtk/dcmimage/dicomot.h
+ dcmimgle/include/dcmtk/dcmimgle/dimocpt.h
+ dcmimgle/include/dcmtk/dcmimgle/dimoflt.h
+ dcmimgle/include/dcmtk/dcmimgle/dimorot.h
+ dcmimgle/include/dcmtk/dcmimgle/dimosct.h
+
+- Use non-throwing new operator to avoid crash:
+ Use a non-throwing new operator to avoid a possible crash when allocating
+ huge amounts of memory. Before, an uncatched C++ exception could be thrown
+ when processing an incorrectly encoded DICOM image.
+ Thanks to drak <dr4k.sec@gmail.com> for the report and sample file.
+ Affects: dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h
+
+**** Changes from 2025.03.03 (eichelberg)
+
+- Fixed ANNOUNCE.369.
+ Affects: docs/ANNOUNCE.369
+
+- Fixed segfault in JPEG-LS decoder:
+ Fixed a bug in the JPEG-LS decoder that led to a segmentation fault if invalid
+ input data was processed, due to insufficient validation of input data.
+ Thanks to Ding zhengzheng <xiaozheng.ding399@gmail.com> for the report
+ and the sample file (PoC).
+ This closes DCMTK issue #1155.
+ Affects: dcmjpls/libcharls/scan.h
+
+- Fixed bug in RLE decoder:
+ Fixed bug in RLE decoder that caused an application crash when an RLE
+ compressed image with a defective RLE header was processed.
+ Thanks to Simeon Stoykov <simeon@microdicom.com> for the bug report
+ and test file.
+ Affects: dcmdata/libsrc/dcrleccd.cc
+
+**** Changes from 2025.03.02 (riesmeier)
+
+- Always return unknown PDU type with two digits:
+ In case of error, return a status message with two digits (hexadecimal
+ notation) for the unknown PDU type.
+ Affects: dcmnet/libsrc/dulfsm.cc
+
+**** Changes from 2025.02.28 (eichelberg)
+
+- Fixed BMP to DICOM conversion on big-endian CPUs.
+ Affects: dcmdata/apps/img2dcm.cc
+ dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h
+ dcmdata/libi2d/i2d.cc
+
+- Fixed STL file size validation on big-endian CPUs.
+ Affects: dcmdata/libsrc/dcencdoc.cc
+
+**** Changes from 2025.02.27 (riesmeier)
+
+- Added SOP Class to "DICOM Conformance" section:
+ Added Rendition Selection Document Real-Time Communication SOP Class
+ to the list of supported SOP Classes, although it is not a Storage
+ SOP Class but used for Real-Time Communication (see DICOM PS3.22).
+ Affects: dcmsr/docs/dsr2html.man
+ dcmsr/docs/dsr2xml.man
+ dcmsr/docs/dsrdump.man
+ dcmsr/docs/xml2dsr.man
+
+**** Changes from 2025.02.26 (eichelberg)
+
+- Fixed byte order when decoding JPEG-LS on big endian:
+ When running on a big endian architecture, the byte swapping algorithm
+ in the JPEG-LS decoder produced incorrect output when decoding an image
+ with an odd frame size.
+ This closes DCMTK issue #1154.
+ Affects: dcmjpls/include/dcmtk/dcmjpls/djcodecd.h
+ dcmjpls/libsrc/djcodecd.cc
+
+- Warn when decoding frame into odd-length buffer:
+ Print a warning to the logger when decodeFrame() operates on an odd-length
+ frame size on a big endian machine, because in this case the last pixel
+ cannot be corrected for byte order.
+ Affects: dcmdata/libsrc/dcrleccd.cc
+ dcmjpeg/libsrc/djcodecd.cc
+
+**** Changes from 2025.02.24 (riesmeier)
+
+- Updated Context Group classes for DICOM 2025a:
+ Updated automatically generated Context Group classes for the latest
+ edition of the DICOM standard. All supported classes were updated,
+ even though there were no changes to most of them.
+ Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid11.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid218.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid244.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid247.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid29.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid42.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7551.h
+ dcmsr/libcmr/cid100.cc
+ dcmsr/libcmr/cid10013.cc
+ dcmsr/libcmr/cid10033.cc
+ dcmsr/libcmr/cid11.cc
+ dcmsr/libcmr/cid218.cc
+ dcmsr/libcmr/cid244.cc
+ dcmsr/libcmr/cid247.cc
+ dcmsr/libcmr/cid29.cc
+ dcmsr/libcmr/cid4020.cc
+ dcmsr/libcmr/cid4021.cc
+ dcmsr/libcmr/cid4031.cc
+ dcmsr/libcmr/cid42.cc
+ dcmsr/libcmr/cid6147.cc
+ dcmsr/libcmr/cid7021.cc
+ dcmsr/libcmr/cid7181.cc
+ dcmsr/libcmr/cid7445.cc
+ dcmsr/libcmr/cid7452.cc
+ dcmsr/libcmr/cid7453.cc
+ dcmsr/libcmr/cid7464.cc
+ dcmsr/libcmr/cid7469.cc
+ dcmsr/libcmr/cid7551.cc
+
+- Updated code definitions for DICOM 2025a:
+ Updated automatically generated code definitions for coding scheme "NCIt".
+ For the coding schemes "DCM" and "UMLS", there were no changes.
+ Affects: dcmsr/include/dcmtk/dcmsr/codes/dcm.h
+ dcmsr/include/dcmtk/dcmsr/codes/ncit.h
+ dcmsr/include/dcmtk/dcmsr/codes/umls.h
+
+- Updated data dictionary for DICOM 2025a:
+ Updated data dictionary for the latest edition of the DICOM standard.
+ Affects: dcmdata/data/dicom.dic
+ dcmdata/include/dcmtk/dcmdata/dcdeftag.h
+ dcmdata/libsrc/dcdictbi.cc
+
+**** Changes from 2025.02.23 (eichelberg)
+
+- Fixed Solaris/OpenIndiana build.
+ Affects: dcmdata/libsrc/dcvrod.cc
+ dcmdata/libsrc/dcvrof.cc
+
+**** Changes from 2025.02.21 (riesmeier)
+
+- Avoid possible output of "-nan" in XML format:
+ Avoid possible output of "-nan" in XML format in order to be consistent
+ throughout the toolkit and to avoid problems when reading such data.
+ This closes DCMTK Bug #1153.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the report
+ and sample instructions to reproduce this issue.
+ Affects: dcmdata/libsrc/dcvrod.cc
+ dcmdata/libsrc/dcvrof.cc
+ dcmsr/libsrc/dsrnumvl.cc
+
+- Made sure float/double values use a decimal point:
+ Made sure that floating point and double values use a proper decimal
+ point when output to a C++ stream. This requires to explicitly set the
+ "C" locale in case the user changed the default, i.e. the global locale.
+ This partly closes DCMTK Bug #1153.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the report
+ on a related issue (that is not yet fixed).
+ Affects: dcmdata/libsrc/dcvrod.cc
+ dcmdata/libsrc/dcvrof.cc
+ dcmimgle/libsrc/dicielut.cc
+ dcmimgle/libsrc/digsdlut.cc
+ dcmsr/libsrc/dsrnumvl.cc
+
+**** Changes from 2025.02.21 (eichelberg)
+
+- Added support for "-nan" in OFStandard::atof():
+ OFStandard::atof() will now accept "-nan" as a valid string
+ and convert it to a quiet NaN.
+ Affects: ofstd/libsrc/ofstd.cc
+
+- Updated some comments.
+ Affects: ofstd/libsrc/ofstd.cc
+
+**** Changes from 2025.02.21 (riesmeier)
+
+- Report warning on incorrect Mapping Resource UID:
+ Output a warning message when reading the UID that is defined for the
+ DICOM Content Mapping Resource (DCMR) for a different Mapping Resource.
+ Also tried to harmonized capitalization of DICOM names in comments.
+ Affects: dcmsr/libsrc/dsrdoctn.cc
+
+**** Changes from 2025.02.20 (riesmeier)
+
+- Report warning on unexpected Verifying Observers:
+ Output a warning message when reading Verifying Observer(s) from a
+ document (DICOM or XML) that has a Verification Flag of "UNVERIFIED".
+ Affects: dcmsr/libsrc/dsrdoc.cc
+
+**** Changes from 2025.02.20 (eichelberg)
+
+- Fixed minor inconsistency in macro definition.
+ Affects: ofstd/libsrc/ofstd.cc
+
+**** Changes from 2025.02.20 (riesmeier)
+
+- Increased precision of float/double output to XML:
+ Increased precision of float output to 9 and double to 17 in order to be
+ "lossless" when writing/reading to/from XML format.
+ Affects: dcmdata/libsrc/dcvrof.cc
+ dcmsr/libsrc/dsrnumvl.cc
+
+**** Changes from 2025.02.20 (eichelberg)
+
+- Refuse compilation on platforms without 64-bit int:
+ Refuse compilation on platforms where no 64-bit integers are available.
+ This is necessary since the Uint64/Sint64 typedefs are meanwhile used in
+ various places in the toolkit.
+ Affects: ofstd/include/dcmtk/ofstd/offile.h
+ ofstd/include/dcmtk/ofstd/ofrand.h
+ ofstd/include/dcmtk/ofstd/oftypes.h
+ ofstd/libsrc/ofrand.cc
+
+**** Changes from 2025.02.19 (riesmeier)
+
+- Fixed wrong Doxygen subsection labels.
+ Affects: dcmdata/docs/dcm2pdf.man
+
+- Used "@note" in Doxgen's API documentation:
+ Used "@note" command in Doxygen's API documentation to highlight when
+ certain methods are only applicable to particular VRs.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h
+
+- Added putAndInsertXXX() methods for 64-bit VRs:
+ Added helper methods putAndInsertUint64(), putAndInsertUint64Array(),
+ putAndInsertSint64() and putAndInsertSint64Array() for the still
+ rather new 64-bit VRs "SV", "UV" and "OV".
+ Affects: dcmdata/include/dcmtk/dcmdata/dcitem.h
+ dcmdata/libsrc/dcitem.cc
+
+- Added missing virtual functions to base class:
+ Added missing virtual functions putUint64(), putSint64(), putUint64Array()
+ and putSint64Array() to the DcmElement class. Apparently, they were
+ forgotten when support for the 64-bit VRs "SV", "UV" and "OV" was added
+ some years ago.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the report.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcelem.h
+ dcmdata/libsrc/dcelem.cc
+
+**** Changes from 2025.02.17 (malaterre)
+
+- Provide a hook to setup iconv path at runtime:
+ Provide a new function OFiconv_setpath() that allows an application
+ to change the iconv data path at runtime. Note: the DCMICONVPATH
+ environment variable will override any path set with this function.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the pull request.
+ This closes GitHub PR #116.
+ Affects: oficonv/include/dcmtk/oficonv/iconv.h
+ oficonv/libsrc/citrus_bcs.c
+ oficonv/libsrc/oficonv_iconv.c
+
+**** Changes from 2025.02.12 (riesmeier)
+
+- Fixed issue with icon image of IMAGE content item:
+ Fixed issue with the optional icon image of an IMAGE content item that
+ was not copied when the setValue() method was called. Depending on how
+ the underlying DSRImageReferenceValue class was used, this resulted in
+ the Icon Image Sequence (0088,0200) missing in the created DICOM dataset.
+ Also added new regression tests that make sure that the icon image is
+ created correctly and copied when needed.
+ Thanks to forum user "pintagliata" for the original report.
+ Added: dcmsr/tests/tsrimgvl.cc
+ Affects: dcmsr/include/dcmtk/dcmsr/dsrimgvl.h
+ dcmsr/libsrc/dsrimgvl.cc
+ dcmsr/tests/CMakeLists.txt
+ dcmsr/tests/Makefile.dep
+ dcmsr/tests/Makefile.in
+ dcmsr/tests/tests.cc
+
+**** Changes from 2025.02.11 (riesmeier)
+
+- Added "datadir" and "docdir" to CMake config:
+ Added CMake variables CMAKE_INSTALL_DATADIR and CMAKE_INSTALL_DOCDIR
+ to the DCMTK configuration that is exported to "DCMTKConfig.cmake".
+ This is particularly important as both paths usually contain the DCMTK
+ version number, which might not be known to the project that imports
+ the DCMTK configuration.
+ Also added quotation marks to all exported installation subdirectories
+ so that spaces and other "special" characters are supported.
+ Affects: CMake/DCMTKConfig.cmake.in
+
+**** Changes from 2025.02.11 (eichelberg)
+
+- Fixed precision when converting double to text:
+ Fixed a bug in OFStandard::ftoa() that caused floating point numbers
+ to be converted/printed with less precision than requested.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the
+ bug report and test file.
+ Affects: ofstd/libsrc/ofstd.cc
+
+**** Changes from 2025.02.11 (riesmeier)
+
+- Fixed calculation of no. of TLS 1.3 cipher suites:
+ Fixed wrong calculation of number of TLS 1.3 cipher suites.
+ Thanks to forum user "Shaeto" for the report.
+ Affects: dcmtls/libsrc/tlsciphr.cc
+
+**** Changes from 2025.02.07 (eichelberg)
+
+- Removed conditional code for very old MSVC versions:
+ Removed conditionally compiled code for very old MSVC versions
+ (Visual Studio 2010 and older) that are not supported anymore,
+ in order to reduce the amount of dead code in the toolkit.
+ Affects: CMake/osconfig.h.in
+ dcmdata/tests/tfilter.cc
+ dcmjpls/libcharls/lltraits.h
+ oflog/include/dcmtk/oflog/config.h
+ oflog/include/dcmtk/oflog/config/win32.h
+ oflog/libsrc/log4judp.cc
+ oflog/libsrc/threads.cc
+ oflog/libsrc/timehelp.cc
+ ofstd/include/dcmtk/ofstd/ofcmdln.h
+ ofstd/include/dcmtk/ofstd/ofmem.h
+ ofstd/include/dcmtk/ofstd/ofoption.h
+
+**** Changes from 2025.02.07 (riesmeier)
+
+- Replaced spaces by tab character for indendation.
+ Affects: ofstd/libsrc/Makefile.in
+
+- Added line break for 80-characters-per-line limit.
+ Affects: dcmpstat/docs/dcmprscp.man
+ dcmpstat/docs/dcmprscu.man
+
+- Added missing newline to "FILES" section.
+ Affects: dcmsr/docs/dsr2html.man
+
+**** Changes from 2025.02.07 (eichelberg)
+
+- Added class that computes SHA-256 checksums:
+ Added a class in ofstd that computes SHA-256 checksums and does not depend
+ on OpenSSL. The code is based on the SHA-256 implementation by
+ Brad Conte (brad AT bradconte.com) in FreeBSD.
+ Added: ofstd/include/dcmtk/ofstd/ofsha256.h
+ ofstd/libsrc/ofsha256.cc
+ Affects: ofstd/libsrc/CMakeLists.txt
+ ofstd/libsrc/Makefile.in
+
+**** Changes from 2025.02.06 (riesmeier)
+
+- Fixed source code formatting.
+ Affects: dcmdata/libsrc/dcjson.cc
+
+**** Changes from 2025.02.05 (riesmeier)
+
+- Fixed minor documentation errors:
+ Fixed wrong struct name in documentation sample code. Also fixed various
+ other minor issues in API documentation and comments.
+ Thanks to GitHub user "malaterre" the original report and proposed patch.
+ This closes GitHub pull request #115.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcjson.h
+ dcmdata/libsrc/dcjson.cc
+
+- Reverted accidentally committed changes:
+ Reverted changes that were accidentally committed with commit 9a0189b5a.
+ Instead, added a comment that there is still a TODO for handling incoming
+ C-ECHO requests.
+ Affects: dcmnet/libsrc/dstorscp.cc
+
+- Removed space between CMake command and "(".
+ Affects: CMake/3rdparty.cmake
+ CMake/GenerateDCMTKConfigure.cmake
+ CMake/dcmtkPrepare.cmake
+
+**** Changes from 2025.02.04 (riesmeier)
+
+- Added the usual note for development versions.
+ Affects: INSTALL
+ dcmnet/libsrc/dstorscp.cc
+
+**** Changes from 2025.02.04 (eichelberg)
+
+- Silently remove trailing zero bytes in strings:
+ Silently remove trailing zero bytes in character string VRs
+ if dcmEnableAutomaticInputDataCorrection is enabled.
+ This closes DCMTK issue #1014.
+ Affects: dcmdata/libsrc/dcbytstr.cc
+
+- Updated INSTALL for previous commit.
+ Affects: INSTALL
+
+- Stop cmake with error message if C++ standard is 98:
+ Stop with an error message if somebody tries to compile DCMTK with a compiler
+ that either does not support C++11, or is configured via CMAKE_CXX_STANDARD
+ to only use C++98. For now, compilation with C++98 can be enabled be running
+ cmake -DDCMTK_PERMIT_CXX98=ON, but this will not work anymore in future
+ DCMTK releases.
+ Affects: CMake/GenerateDCMTKConfigure.cmake
+ CMake/dcmtkPrepare.cmake
+
+**** Changes from 2025.01.30 (eichelberg)
+
+- Fixed minor warnings.
+ Affects: dcmdata/libi2d/i2djpgs.cc
+ dcmdata/libi2d/i2dplnsc.cc
+ dcmdata/libi2d/i2dplop.cc
+ dcmdata/libi2d/i2dplvlp.cc
+
+**** Changes from 2025.01.29 (eichelberg)
+
+- Improved handling of JPEG image files:
+ Improved the handling of JPEG image files as input to img2dcm. Several special
+ cases such as different types of component subsampling, as well as lossy
+ JPEG images in RGB or CMYK color (instead of YCbCr) are now correctly
+ handled, and rejected if necessary.
+ This closes DCMTK issue #995.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the suggestion.
+ Affects: dcmdata/include/dcmtk/dcmdata/libi2d/i2d.h
+ dcmdata/include/dcmtk/dcmdata/libi2d/i2djpgs.h
+ dcmdata/include/dcmtk/dcmdata/libi2d/i2doutpl.h
+ dcmdata/include/dcmtk/dcmdata/libi2d/i2dplnsc.h
+ dcmdata/include/dcmtk/dcmdata/libi2d/i2dplop.h
+ dcmdata/include/dcmtk/dcmdata/libi2d/i2dplsc.h
+ dcmdata/include/dcmtk/dcmdata/libi2d/i2dplvlp.h
+ dcmdata/libi2d/i2d.cc
+ dcmdata/libi2d/i2djpgs.cc
+ dcmdata/libi2d/i2dplnsc.cc
+ dcmdata/libi2d/i2dplop.cc
+ dcmdata/libi2d/i2dplsc.cc
+ dcmdata/libi2d/i2dplvlp.cc
+
+**** Changes from 2025.01.28 (riesmeier)
+
+- Avoid warning on unused variable:
+ Avoid warning on unused variable when compiled without character set
+ conversion support.
+ Affects: dcmsr/apps/dsr2html.cc
+ dcmsr/apps/dsrdump.cc
+
+**** Changes from 2025.01.25 (riesmeier)
+
+- Added support for the Context Group Keyword:
+ Added support for the official Context Group Keyword that was introduced
+ for all Context Groups of the DICOM Content Mapping Resource (DCMR, see
+ DICOM PS3.16) with CP-2181.
+ This change required to regenerate all automatically generated Context
+ Group classes (still based on DICOM 2024e).
+ This closes DCMTK Feature #1033.
+ Affects: dcmsr/include/dcmtk/dcmsr/cmr/cid100.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10013.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid10033.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid11.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid218.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid244.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid247.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid29.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4020.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid4031.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid42.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid6147.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7021.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7181.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7445.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7452.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7453.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7464.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7469.h
+ dcmsr/include/dcmtk/dcmsr/cmr/cid7551.h
+ dcmsr/include/dcmtk/dcmsr/dsrctxgr.h
+ dcmsr/libcmr/cid100.cc
+ dcmsr/libcmr/cid10013.cc
+ dcmsr/libcmr/cid10033.cc
+ dcmsr/libcmr/cid11.cc
+ dcmsr/libcmr/cid218.cc
+ dcmsr/libcmr/cid244.cc
+ dcmsr/libcmr/cid247.cc
+ dcmsr/libcmr/cid29.cc
+ dcmsr/libcmr/cid4020.cc
+ dcmsr/libcmr/cid4021.cc
+ dcmsr/libcmr/cid4031.cc
+ dcmsr/libcmr/cid42.cc
+ dcmsr/libcmr/cid5000.cc
+ dcmsr/libcmr/cid5001.cc
+ dcmsr/libcmr/cid6147.cc
+ dcmsr/libcmr/cid7021.cc
+ dcmsr/libcmr/cid7181.cc
+ dcmsr/libcmr/cid7445.cc
+ dcmsr/libcmr/cid7452.cc
+ dcmsr/libcmr/cid7453.cc
+ dcmsr/libcmr/cid7464.cc
+ dcmsr/libcmr/cid7469.cc
+ dcmsr/libcmr/cid7551.cc
+ dcmsr/libsrc/dsrctxgr.cc
+ dcmsr/tests/tsrcmr.cc
+
+**** Changes from 2025.01.24 (eichelberg)
+
+- Improved diagnostic log output.
+ Affects: dcmdata/libsrc/dcrleccd.cc
+
+**** Changes from 2025.01.23 (eichelberg)
+
+- Fixed issue with invalid RLE compressed DICOM images:
+ Fixed issue when processing an RLE compressed image where the RLE header
+ contains an invalid stripe size.
+ Thanks to Ding zhengzheng <xiaozheng.ding399@gmail.com> for the report
+ and the sample file (PoC).
+ Affects: dcmdata/libsrc/dcrleccd.cc
+
+**** Changes from 2025.01.22 (eichelberg)
+
+- Fixed access rights.
+ Affects: docs/ANNOUNCE.369
+
+**** Changes from 2025.01.21 (riesmeier)
+
+- Made sure all member variables are initialized:
+ Initialized member variable that was missing in the member initializer
+ list of the constructor. This issue was reported at runtime when compiling
+ with gcc and option -fsanitize=undefined.
+ Affects: dcmiod/libsrc/modmultiframedimension.cc
+
+- Fixed another issue with invalid DICOM images:
+ Fixed issue when processing an invalid DICOM image where the number of
+ pixels stored does not match the expected number of pixels (too less)
+ and the combination of BitsAllocated and BitsStored is really unusual
+ (e.g. 1 bit stored, but 52 bits allocated). In cases where the last
+ pixel (e.g. a single bit) does not fit into the buffer of the input
+ pixel data, a buffer overflow occurred on the heap. Now, the last entry
+ of the buffer is filled with the smallest possible value (e.g. 0 in case
+ of unsigned data).
+ Thanks to Ding zhengzheng <xiaozheng.ding399@gmail.com> for the report
+ and the sample file (PoC).
+ Affects: dcmimgle/include/dcmtk/dcmimgle/diinpxt.h
+
+- Don't call getAbsMinimum() in a for-loop:
+ Use a local constant instead of calling getAbsMinimum() in a for-loop,
+ even if it is probably expanded as an inline function.
+ Affects: dcmimgle/include/dcmtk/dcmimgle/diinpxt.h
+
+**** Changes from 2025.01.20 (riesmeier)
+
+- Removed further outdated Autoconf tests:
+ See commits 09017a3cb and 95c799f57 for details and the corresponding
+ CMake changes.
+ Affects: config/aclocal.m4
+ config/configure
+ config/configure.in
+ config/confmod
+ config/include/dcmtk/config/osconfig.h.in
+
+**** Changes from 2025.01.20 (eichelberg)
+
+- Further clean-up of outdated configure tests.
+ Affects: CMake/GenerateDCMTKConfigure.cmake
+ CMake/osconfig.h.in
+
+**** Changes from 2025.01.19 (eichelberg)
+
+- Fixed character set conversion in dcm2json:
+ Fixed character set conversion in dcm2json for the case that an extended
+ character set is used but that character set that does not contain byte
+ positions > 127 (such as ISO_IR 87) and is thus not detected by
+ DcmItem::containsExtendedCharacters().
+ Affects: dcmdata/apps/dcm2json.cc
+
+- Fixed debug build on Win32.
+ Affects: dcmdata/libsrc/dcistrmz.cc
+
+**** Changes from 2025.01.18 (eichelberg)
+
+- Further clean-up of outdated configure tests:
+ Cleaned up configure tests that checked for features that are not used
+ in DCMTK anymore or that are not in use anymore on any of the supported
+ operating systems (e.g. pre-POSIX APIs and header files).
+ Affects: CMake/GenerateDCMTKConfigure.cmake
+ CMake/osconfig.h.in
+ config/docs/macros.txt
+ config/math.cc
+ dcmapps/include/dcmtk/dcmapps/dcm2img.h
+ dcmdata/apps/dcm2pdf.cc
+ dcmdata/apps/dump2dcm.cc
+ dcmdata/include/dcmtk/dcmdata/dctypes.h
+ dcmdata/libdcxml/xml2dcm.cc
+ dcmdata/libsrc/cmdlnarg.cc
+ dcmdata/libsrc/dcbytstr.cc
+ dcmdata/libsrc/dcelem.cc
+ dcmdata/libsrc/dcistrmf.cc
+ dcmdata/libsrc/dcistrms.cc
+ dcmdata/libsrc/dcostrmf.cc
+ dcmdata/libsrc/dcostrms.cc
+ dcmdata/libsrc/dcuid.cc
+ dcmimage/include/dcmtk/dcmimage/dicopxt.h
+ dcmimage/include/dcmtk/dcmimage/diqtpbox.h
+ dcmimgle/include/dcmtk/dcmimgle/diinpxt.h
+ dcmimgle/include/dcmtk/dcmimgle/dimopxt.h
+ dcmjpeg/libijg12/jconfig12.h
+ dcmjpeg/libijg12/jerror.c
+ dcmjpeg/libijg16/jconfig16.h
+ dcmjpeg/libijg16/jerror.c
+ dcmjpeg/libijg8/jconfig8.h
+ dcmjpeg/libijg8/jerror.c
+ dcmjpls/libcharls/encodstr.h
+ dcmjpls/libcharls/streams.h
+ dcmjpls/libsrc/djcodece.cc
+ dcmnet/apps/storescp.cc
+ dcmnet/include/dcmtk/dcmnet/dcompat.h
+ dcmnet/libsrc/assoc.cc
+ dcmnet/libsrc/dcmtrans.cc
+ dcmnet/libsrc/dcompat.cc
+ dcmnet/libsrc/dimcancl.cc
+ dcmnet/libsrc/dimcmd.cc
+ dcmnet/libsrc/dimdump.cc
+ dcmnet/libsrc/dimfind.cc
+ dcmnet/libsrc/dimget.cc
+ dcmnet/libsrc/dimmove.cc
+ dcmnet/libsrc/dimse.cc
+ dcmnet/libsrc/dimstore.cc
+ dcmnet/libsrc/diutil.cc
+ dcmnet/libsrc/dul.cc
+ dcmnet/libsrc/dulextra.cc
+ dcmnet/libsrc/dulfsm.cc
+ dcmpstat/apps/dcmprscp.cc
+ dcmpstat/apps/dcmprscu.cc
+ dcmpstat/apps/dcmpsrcv.cc
+ dcmpstat/apps/dcmpssnd.cc
+ dcmpstat/libsrc/dviface.cc
+ dcmpstat/libsrc/dvpshlp.cc
+ dcmpstat/tests/msgserv.cc
+ dcmqrdb/apps/dcmqrscp.cc
+ dcmqrdb/libsrc/dcmqrcbg.cc
+ dcmqrdb/libsrc/dcmqrcbm.cc
+ dcmqrdb/libsrc/dcmqrcnf.cc
+ dcmqrdb/libsrc/dcmqrdbi.cc
+ dcmqrdb/libsrc/dcmqrtis.cc
+ dcmsr/libsrc/dsrxmld.cc
+ dcmtls/libsrc/tlstrans.cc
+ dcmwlm/libsrc/wldsfs.cc
+ oficonv/apps/mkcsmapper.y
+ oficonv/apps/mkcsmapper_bison.cc
+ oficonv/apps/mkcsmapper_bison.h
+ oficonv/apps/mkesdb.y
+ oficonv/apps/mkesdb_bison.cc
+ oficonv/apps/mkesdb_bison.h
+ oficonv/include/dcmtk/oficonv/iconv.h
+ oficonv/libsrc/citrus_bcs.h
+ oficonv/libsrc/citrus_big5.c
+ oficonv/libsrc/citrus_csmapper.c
+ oficonv/libsrc/citrus_db.c
+ oficonv/libsrc/citrus_db_factory.c
+ oficonv/libsrc/citrus_db_hash.c
+ oficonv/libsrc/citrus_dechanyu.c
+ oficonv/libsrc/citrus_esdb.c
+ oficonv/libsrc/citrus_euc.c
+ oficonv/libsrc/citrus_euctw.c
+ oficonv/libsrc/citrus_gbk2k.c
+ oficonv/libsrc/citrus_hash.c
+ oficonv/libsrc/citrus_hz.c
+ oficonv/libsrc/citrus_iconv.c
+ oficonv/libsrc/citrus_iso2022.c
+ oficonv/libsrc/citrus_jisx0208.c
+ oficonv/libsrc/citrus_johab.c
+ oficonv/libsrc/citrus_lookup.c
+ oficonv/libsrc/citrus_mapper.c
+ oficonv/libsrc/citrus_mmap.c
+ oficonv/libsrc/citrus_module.c
+ oficonv/libsrc/citrus_mskanji.c
+ oficonv/libsrc/citrus_none.c
+ oficonv/libsrc/citrus_region.h
+ oficonv/libsrc/citrus_types.h
+ oficonv/libsrc/citrus_utf1632.c
+ oficonv/libsrc/citrus_utf8.c
+ oficonv/libsrc/citrus_viqr.c
+ oficonv/libsrc/citrus_zw.c
+ oficonv/libsrc/oficonv_iconv.c
+ oflog/include/dcmtk/oflog/config/defines.h
+ ofstd/include/dcmtk/ofstd/ofdate.h
+ ofstd/include/dcmtk/ofstd/offile.h
+ ofstd/include/dcmtk/ofstd/oflist.h
+ ofstd/include/dcmtk/ofstd/ofsockad.h
+ ofstd/include/dcmtk/ofstd/ofstd.h
+ ofstd/include/dcmtk/ofstd/ofstdinc.h
+ ofstd/include/dcmtk/ofstd/ofstream.h
+ ofstd/include/dcmtk/ofstd/oftempf.h
+ ofstd/include/dcmtk/ofstd/oftime.h
+ ofstd/include/dcmtk/ofstd/oftypes.h
+ ofstd/include/dcmtk/ofstd/ofvector.h
+ ofstd/libsrc/ofconsol.cc
+ ofstd/libsrc/ofdatime.cc
+ ofstd/libsrc/offilsys.cc
+ ofstd/libsrc/offname.cc
+ ofstd/libsrc/ofipc.cc
+ ofstd/libsrc/ofstd.cc
+
+**** Changes from 2025.01.17 (riesmeier)
+
+- Fixed another issue with invalid mono images:
+ Fixed issue when rendering an invalid monochrome DICOM image where the
+ number of pixels stored does not match the expected number of pixels.
+ In this case, only a single pixel is processed, but the pixel matrix is
+ much larger. Filling the rest of the pixel matrix with the smallest
+ possible value for the image is not working because of an optimized
+ memory usage (value would be out of range). Now, the pixel value to be
+ used is double-checked before it is actually filled into the "background"
+ of the image.
+ Thanks to Ding zhengzheng <xiaozheng.ding399@gmail.com> for the report
+ and the sample file (PoC).
+ Affects: dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h
+
+- Made sure that memory is always cleaned up:
+ Made sure that allocated memory is always cleaned up, i.e. also in case
+ of error. Otherwise, tools like ASAN will report memory leaks.
+ Affects: dcmapps/include/dcmtk/dcmapps/dcm2img.h
+
+- Do not exceed the maximum size of DcmList:
+ Made sure that the maximum number of entries of an DcmList instance is
+ not exceeded. Even if it is unlikely, NULL is returned and a message is
+ output to the debug logger.
+ Affects: dcmdata/include/dcmtk/dcmdata/dclist.h
+ dcmdata/libsrc/dclist.cc
+
+- Further optimizations of DcmList:seek_to():
+ Handle the special cases seek_to() first and last item in the list more
+ efficiently. Also avoid unnecessary call of DcmList::get() in case of an
+ invalid position.
+ Affects: dcmdata/libsrc/dclist.cc
+
+- Replaced call of DcmList::seek_to() by seek():
+ Replaced call of DcmList::seek_to() by seek() for accessing the first
+ and the last item of the list. This should slightly improve the
+ performance when DcmFileFormat::getMetaInfo() or getDataset() are called
+ many times.
+ Affects: dcmdata/libsrc/dcfilefo.cc
+
+- Improved performance of DcmList::seek_to():
+ Significantly improved the performance of the seek_to() method, in
+ particular when iterating a very long list using the position of the
+ items, e.g. a DcmPixelSequence with a huge number of instances of
+ DcmPixelItem such as in Whole Slide Imaging (WSI) objects. Internally,
+ the seek_to() method is, e.g., used in the insert(), remove() and
+ getItem() methods of DcmSequenceOfItems and DcmPixelSequence as well
+ as in the getElement() and remove() method of DcmItem.
+ Thanks to GitHub user "reunanen" for the report and proposed patch.
+ This closes GitHub pull request #114.
+ Affects: dcmdata/include/dcmtk/dcmdata/dclist.h
+ dcmdata/libsrc/dclist.cc
+ dcmdata/tests/tsequen.cc
+
+**** Changes from 2025.01.17 (eichelberg)
+
+- Fixed handling of SpecificCharacterSet in sequences:
+ Fixed the handling of files where SpecificCharacterSet may occur
+ in sequence items and where different items might use different
+ character sets, such as DICOMDIRs.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com>
+ for pointing out the issue.
+ Affects: dcmdata/apps/dcm2json.cc
+
+**** Changes from 2025.01.15 (riesmeier)
+
+- Made a minor change to the API documentation.
+ Affects: dcmsr/include/dcmtk/dcmsr/dsrdoc.h
+
+**** Changes from 2025.01.14 (riesmeier)
+
+- Restructured code of method convertString():
+ Restructured code of the convertString() method by splitting it into two
+ methods: one for strings without and one for strings with code extension
+ techniques according to ISO 2022. This should increase the readability
+ of the code.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcspchrs.h
+ dcmdata/libsrc/dcspchrs.cc
+
+**** Changes from 2025.01.13 (eichelberg)
+
+- Fixed HAVE_PROTOTYPE_FEENABLEEXCEPT configure test.
+ Affects: CMake/GenerateDCMTKConfigure.cmake
+
+- Fixed a few memory leaks in unit tests.
+ Affects: dcmdata/tests/tfrmsiz.cc
+ dcmect/tests/t_overflow.cc
+ dcmfg/tests/t_fg_base.cc
+ dcmseg/tests/tutils.cc
+
+- Fixed two memory leaks in oficonv.
+ Affects: oficonv/include/dcmtk/oficonv/iconv.h
+ oficonv/libsrc/citrus_iconv.c
+ oficonv/libsrc/citrus_iconv.h
+ oficonv/libsrc/citrus_mapper_zone.c
+ oficonv/libsrc/oficonv_iconv.c
+ oficonv/tests/tests.cc
+ oficonv/tests/ticonv.cc
+
+**** Changes from 2025.01.13 (riesmeier)
+
+- Enhanced dcm2xml's support for DICOMDIR files:
+ Fixed conversion of DICOMDIR files to UTF-8 encoding (i.e. when using
+ option +U8) by removing an irritating error message and making sure
+ that no SpecificCharacterSet element is added to the top-level dataset.
+ Affects: dcmdata/apps/dcm2xml.cc
+
+**** Changes from 2025.01.11 (riesmeier)
+
+- Fixed issue rendering invalid monochrome image:
+ Fixed issue when rendering an invalid monochrome DICOM image where the
+ number of pixels stored does not match the expected number of pixels.
+ If the stored number is less than the expected number, the rest of the
+ pixel matrix for the intermediate representation was always filled with
+ the value 0. Under certain, very rare conditions, this could result in
+ memory problems reported by an Address Sanitizer (ASAN). Now, the rest
+ of the matrix is filled with the smallest possible value for the image.
+ Thanks to Emmanuel Tacheau from the Cisco Talos team
+ <vulndiscovery@external.cisco.com> for the original report, the sample
+ file (PoC) and further details. See TALOS-2024-2122 and CVE-2024-47796.
+ Affects: dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h
+
+- Enhanced check for invalid NULL parameter:
+ Even if the passed value should never be NULL, such a check does not
+ do any harm.
+ Affects: dcmimgle/include/dcmtk/dcmimgle/dimoipxt.h
+
+- Replaced call of delete by delete[]:
+ This issue has been reported by the gcc address sanitizer (using option
+ -fsanitize=address).
+ Affects: dcmimgle/libsrc/diimage.cc
+
+**** Changes from 2025.01.10 (riesmeier)
+
+- Fixed issue with Doxygen grouping markup:
+ Fixed issue with grouping markup when using newer Doxygen versions.
+ Affects: dcmdata/include/dcmtk/dcmdata/dcbytstr.h
+ dcmdata/include/dcmtk/dcmdata/dcerror.h
+ dcmdata/include/dcmtk/dcmdata/dctypes.h
+ dcmimgle/include/dcmtk/dcmimgle/diutils.h
+ dcmrt/include/dcmtk/dcmrt/drttypes.h
+ dcmseg/include/dcmtk/dcmseg/segtypes.h
+ dcmsr/include/dcmtk/dcmsr/cmr/tid1500.h
+ dcmsr/include/dcmtk/dcmsr/cmr/tid15def.h
+ dcmsr/include/dcmtk/dcmsr/cmr/tid1600.h
+ dcmsr/include/dcmtk/dcmsr/dsrtypes.h
+ ofstd/include/dcmtk/ofstd/ofchrenc.h
+ ofstd/include/dcmtk/ofstd/ofcond.h
+ ofstd/include/dcmtk/ofstd/ofstd.h
+ ofstd/include/dcmtk/ofstd/oftest.h
+
+**** Changes from 2025.01.06 (eichelberg)
+
+- Fixed minor warning on MSVC.
+ Affects: ofstd/tests/tstring.cc
+
+**** Changes from 2025.01.05 (riesmeier)
+
+- Fixed wrong capitalization of acronym "JSON".
+ Affects: dcmdata/libsrc/dcjson.cc
+ dcmdata/libsrc/dcvrds.cc
+ dcmdata/libsrc/dcvris.cc
+
+**** Changes from 2025.01.05 (eichelberg)
+
+- Added OFString/std::string conversion helpers:
+ Added helper functions to convert between std::string and OFString.
+ This closes DCMTK feature #1106.
+ Added: ofstd/include/dcmtk/ofstd/ofstrhlp.h
+ Affects: ofstd/tests/tests.cc
+ ofstd/tests/tstring.cc
+
+**** Changes from 2025.01.04 (eichelberg)
+
+- Added logger warnings when converting invalid IS/DS:
+ Added logger warnings when converting invalid IS/DS values to Json.
+ This closes DCMTK Feature #1084.
+ Affects: dcmdata/libsrc/dcvrds.cc
+ dcmdata/libsrc/dcvris.cc
+
+**** Changes from 2025.01.03 (riesmeier)
+
+- Revised handling of --write-auto option:
+ Revised handling of --write-auto option to avoid unwanted log messages.
+ Also slightly modified log messages for reasons of consistency.
+ Affects: dcmapps/include/dcmtk/dcmapps/dcm2img.h
+
+- Added check to make sure: HighBit < BitsAllocated:
+ Added check to the image preprocessing to make sure that the value of
+ HighBit is always less than the value of BitsAllocated. Before, this
+ missing check could lead to memory corruption if an invalid combination
+ of values was retrieved from a malformed DICOM dataset.
+ Thanks to Emmanuel Tacheau from the Cisco Talos team
+ <vulndiscovery@external.cisco.com> for the report, sample file (PoC)
+ and detailed analysis. See TALOS-2024-2121 and CVE-2024-52333.
+ Affects: dcmimgle/libsrc/diimage.cc
+
+- Avoided warning on unchecked option --write-auto.
+ Affects: dcmapps/include/dcmtk/dcmapps/dcm2img.h
+
+**** Changes from 2024.12.31 (eichelberg)
+
+- Fixed data corruption in iconv passthrough mode:
+ Fixed a data corruption that occured if a string longer than 1024 characters
+ was run through OFiconv() with source and character set being identical
+ and the pass-through mode being enabled (i.e. DCMTK compiled with the macro
+ DCMTK_ENABLE_ICONV_PASSTHROUGH). In this situation, the pointer to the next
+ unprocessed input character was not updated.
+ Thanks to DCMTK forum user cschreib for the bug report and test program.
+ This closes DCMTK issue #1143.
+ Affects: oficonv/libsrc/citrus_iconv_none.c
+
+**** Changes from 2024.12.29 (eichelberg)
+
+- Fixed thread issues in oficonv code:
+ Fixed various thread issues in the oficonv module reported by Valgrind's
+ DRD tool by moving some attributes that are modified during a call to
+ OFiconv_open() from the structure that is shared between multiple
+ iconv handles (struct _citrus_iconv_shared) to the structure containing
+ the unique attributes of each handle (struct _citrus_iconv).
+ Also added a read-write lock protecting accesses to the oficonv
+ logger callback.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the bug report
+ and test program demonstrating the issue.
+ This closes DCMTK issue #1137.
+ Affects: oficonv/libsrc/citrus_iconv_local.h
+ oficonv/libsrc/citrus_iconv_std.c
+ oficonv/libsrc/citrus_lock.h
+ oficonv/libsrc/oficonv_iconv.c
+ oficonv/libsrc/oficonv_logger.c
+
+**** Changes from 2024.12.28 (eichelberg)
+
+- Fixed frame size calculation for special cases:
+ DcmElement::getUncompressedFrameSize() now takes into account special cases
+ such as compressed images where Bits Allocated has a value that is not a
+ multiple of 8, but is overwritten during decompression anyway. In the case
+ of compressed images, the active decoder is now looked up and its behavior is
+ taken into account in the calculation.
+ This closes DCMTK issue #1140.
+ Added: dcmdata/tests/tfrmsiz.cc
+ Affects: dcmdata/include/dcmtk/dcmdata/dccodec.h
+ dcmdata/include/dcmtk/dcmdata/dcelem.h
+ dcmdata/include/dcmtk/dcmdata/dcpixel.h
+ dcmdata/include/dcmtk/dcmdata/dcrleccd.h
+ dcmdata/include/dcmtk/dcmdata/dcrlecce.h
+ dcmdata/libsrc/dccodec.cc
+ dcmdata/libsrc/dcelem.cc
+ dcmdata/libsrc/dcpixel.cc
+ dcmdata/libsrc/dcrleccd.cc
+ dcmdata/libsrc/dcrlecce.cc
+ dcmdata/tests/CMakeLists.txt
+ dcmdata/tests/Makefile.in
+ dcmdata/tests/tests.cc
+ dcmjpeg/include/dcmtk/dcmjpeg/djcodecd.h
+ dcmjpeg/include/dcmtk/dcmjpeg/djcodece.h
+ dcmjpeg/libsrc/djcodecd.cc
+ dcmjpeg/libsrc/djcodece.cc
+ dcmjpls/include/dcmtk/dcmjpls/djcodecd.h
+ dcmjpls/include/dcmtk/dcmjpls/djcodece.h
+ dcmjpls/libsrc/djcodecd.cc
+ dcmjpls/libsrc/djcodece.cc
+
+**** Changes from 2024.12.27 (riesmeier)
+
+- Fixed source code formatting.
+ Affects: dcmimage/libsrc/dipitiff.cc
+
+**** Changes from 2024.12.24 (eichelberg)
+
+- Fixed TIFF export on Windows:
+ Fixed the TIFF export option of the dcm2img tool, which did not work
+ on 32-bit and 64 bit Windows builds.
+ Affects: dcmimage/libsrc/dipitiff.cc
+
+**** Changes from 2024.12.20 (eichelberg)
+
+- Added option that allows to relax GSPS validation:
+ Added an option to the validation code for Grayscale Softcopy Presentation
+ States that allows to relax the rule that all images referenced from one
+ presentation state must belong to the same SOP class. The rule can either
+ be relaxed to permit related "for presentation" and "for processing"
+ SOP classes, or this specific check can be completely disabled.
+ Thanks to Oliver Klerx <klerx@phoenix-pacs.de> for the proposal and patch.
+ Affects: dcmpstat/apps/dcmpschk.cc
+ dcmpstat/apps/dcmpsmk.cc
+ dcmpstat/apps/dcmpsrcv.cc
+ dcmpstat/docs/dcmpschk.man
+ dcmpstat/docs/dcmpsmk.man
+ dcmpstat/etc/dcmpstat.cfg
+ dcmpstat/include/dcmtk/dcmpstat/dvpscf.h
+ dcmpstat/include/dcmtk/dcmpstat/dvpsri.h
+ dcmpstat/libsrc/dvpscf.cc
+ dcmpstat/libsrc/dvpsri.cc
+
+**** Changes from 2024.12.18 (eichelberg)
+
+- Properly handle unknown "localhost" in DVPSIPCClient:
+ The request to resolve the hostname "localhost" to an IPv4 address
+ may fail under certain circumstances (e.g. in a IPv6 only environment).
+ This situation is now handled properly.
+ Thanks to Oliver Klerx <klerx@phoenix-pacs.de> for the bug report and patch.
+ Affects: dcmpstat/libsrc/dvpsmsg.cc
+
+- Simplified DcmQuantColorTable::computeHistogram():
+ Simplified code to avoid bogus error reports from Cppcheck.
+ Thanks to Oliver Klerx <klerx@phoenix-pacs.de> for the suggestion and patch.
+ Affects: dcmimage/libsrc/diqtctab.cc
+
+- Removed duplicate library dependencies (part 2):
+ Removed link libraries that are automatically included by CMake as
+ dependencies from other libraries. This avoids the code to be linked
+ against the same library multiple times, which causes warnings on MacOS.
+ Affects: dcmdata/apps/CMakeLists.txt
+ dcmdata/tests/CMakeLists.txt
+ dcmect/tests/CMakeLists.txt
+ dcmfg/tests/CMakeLists.txt
+ dcmjpls/apps/CMakeLists.txt
+ dcmnet/apps/CMakeLists.txt
+ dcmpstat/apps/CMakeLists.txt
+ dcmpstat/tests/CMakeLists.txt
+ dcmrt/apps/CMakeLists.txt
+ dcmrt/tests/CMakeLists.txt
+ dcmtls/tests/CMakeLists.txt
+ dcmwlm/apps/CMakeLists.txt
+ dcmwlm/tests/CMakeLists.txt
+
+**** Changes from 2024.12.17 (eichelberg)
+
+- Fixed padding of compressed JPEG-LS bitstream:
+ When using the cooked JPEG-LS encoder, odd-length bitstreams were padded with
+ a trailing zero byte (corresponding to the --padding-zero command line option)
+ instead of a an extended EOI marker.
+ Thanks to Mathieu Malaterre <mathieu.malaterre@gmail.com> for the bug report and pull request.
+ This closes Github pull request #111.
+ Affects: dcmjpls/libsrc/djcodece.cc
+
+- Removed duplicate library dependencies:
+ Removed link libraries that are automatically included by CMake as
+ dependencies from other libraries. This avoids the code to be linked
+ against the same library multiple times, which causes warnings on MacOS.
+ Affects: dcmapps/apps/CMakeLists.txt
+
+**** Changes from 2024.12.17 (fedorov)
+
+- Fix environ for Apple:
+ On Apple systems, define environ by using _NSGetEnviron() from
+ crt_externs.h.
+ Affects: ofstd/libsrc/ofstub.cc
+
+**** Changes from 2024.12.16 (riesmeier)
+
+- Replaced call of delete also in destructor.
+ Affects: dcmimgle/libsrc/dimoimg.cc
+
+- Replaced call of delete by delete[]:
+ Memory that was allocated with new[] should be deleted with delete[].
+ Thanks to Oliver Klerx <klerx@phoenix-pacs.de> for the report.
+ Affects: dcmimgle/libsrc/dimoimg.cc
+
+**** Changes from 2024.12.13 (eichelberg)
+
+- Updated version information for 3.6.9+ development.
+ Affects: config/configure
+ config/configure.in
+ config/confmod
+
+- Updated version information for 3.6.9+ development:
+ Updated version information marking the start of DCMTK development post minor
+ release 3.6.9.
+ Moved official ANNOUNCE file of the DCMTK release 3.6.9 to the "docs"
+ subfolder and replaced the main ANNOUNCE file with a "dummy".
+ Added: docs/ANNOUNCE.369
+ Affects: ANNOUNCE
+ CMake/dcmtkPrepare.cmake
+ VERSION
+
+- Updated Github workflow config.
+ Affects: .github/workflows/cmake-win.yml
+
+**** Changes from 2024.12.11 (riesmeier)
+
+- Added missing package date.
+ Affects: config/configure
+ config/configure.in
+
+**** Changes from 2024.12.11 (eichelberg)
+
+- Updated PACKAGE version settings.
+ Affects: config/configure
+ config/configure.in
+
+- Updated configure files for upcoming release.
+ Affects: config/configure
+ config/configure.in
-.TH "cda2dcm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "cda2dcm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
cda2dcm \- Encapsulate CDA file into DICOM file format
.PP
.SH "DESCRIPTION"
.PP
-The \fBcda2dcm\fP utility reads a CDA file (\fIcdafile-in\fP), converts it to a DICOM Encapsulated CDA Storage SOP instance and stores the converted data to an output file (\fIdcmfile-out\fP)\&.
-.SH "PARAMETERS"
+The \fBcda2dcm\fP tool is deprecated\&. Use \fBdcmencap\fP instead, which supports the same command line parameters, and more\&.
+.SH "SEE ALSO"
.PP
-.PP
-.nf
-cdafile-in CDA input filename to be encapsulated
-
-dcmfile-out DICOM output filename ("-" for stdout)
-.fi
-.PP
-.SH "OPTIONS"
-.PP
-.SS "general options"
-.PP
-.nf
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-.fi
-.PP
-.SS "DICOM document options"
-.PP
-.nf
-document title:
-
- +t --title [t]itle: string (default: empty)
- document title
-
- +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
- coded representation of document title defined by coding
- scheme designator CSD, code value CV and code meaning CM
-
-patient data:
-
- +pn --patient-name [n]ame: string
- patient's name in DICOM PN syntax
-
- +pi --patient-id [i]d: string
- patient identifier
-
- +pb --patient-birthdate [d]ate: string (YYYYMMDD)
- patient's birth date
-
- +ps --patient-sex [s]ex: string (M, F or O)
- patient's sex
-
-study and series:
-
- +sg --generate
- generate new study and series UIDs (default)
-
- +st --study-from [f]ilename: string
- read patient/study data from DICOM file
-
- +se --series-from [f]ilename: string
- read patient/study/series data from DICOM file
-
-instance number:
-
- +i1 --instance-one
- use instance number 1 (default, not with +se)
-
- +ii --instance-inc
- increment instance number (only with +se)
-
- +is --instance-set [i]nstance number: integer
- use instance number i
-
-burned-in annotation:
-
- +an --annotation-yes
- document contains patient identifying data (default)
-
- -an --annotation-no
- document does not contain patient identifying data
-
-override CDA file data:
-
- -ov --no-override
- CDA patient and document data must match study,
- series or manually entered information (default)
-
- +ov --override
- data obtained from the CDA file will be overwritten
- by study, series, or manually entered information
-.fi
-.PP
-.SS "processing options"
-.PP
-.nf
-other processing options:
-
- -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
- add further attribute
-.fi
-.PP
-.SS "output options"
-.PP
-.nf
-output file format:
-
- +F --write-file
- write file format (default)
-
- -F --write-dataset
- write data set without file meta information
-
-group length encoding:
-
- +g= --group-length-recalc
- recalculate group lengths if present (default)
-
- +g --group-length-create
- always write with group length elements
-
- -g --group-length-remove
- always write without group length elements
-
-length encoding in sequences and items:
-
- +e --length-explicit
- write with explicit lengths (default)
-
- -e --length-undefined
- write with undefined lengths
-
-data set trailing padding (not with --write-dataset):
-
- -p --padding-off
- no padding (implicit if --write-dataset)
-
- +p --padding-create [f]ile-pad [i]tem-pad: integer
- align file on multiple of f bytes
- and items on multiple of i bytes
-.fi
-.PP
-.SH "NOTES"
-.PP
-.SS "Attribute Sources"
-The application may be fed with some additional input for filling mandatory (and optional) attributes in the new DICOM file like patient, study and series information:
-.PP
-.IP "\(bu" 2
-The \fI--key\fP option can be used to add further attributes to the DICOM output file\&.
-.IP "\(bu" 2
-It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&.
-.IP "\(bu" 2
-The \fI--key\fP option can be present more than once\&.
-.IP "\(bu" 2
-The value part (after the '=') may be absent causing the attribute to be set with zero length\&.
-.IP "\(bu" 2
-Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&.
-.PP
-.SH "LOGGING"
-.PP
-The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
-.PP
-In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
-.SH "COMMAND LINE"
-.PP
-All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
-.PP
-Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
-.PP
-In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
-.SH "EXIT CODES"
-.PP
-The \fBcda2dcm\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
-.SS "general"
-.PP
-.nf
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-EXITCODE_MEMORY_EXHAUSTED 4
-.fi
-.PP
-.SS "input file errors"
-.PP
-.nf
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-.fi
-.PP
-.SS "output file errors"
-.PP
-.nf
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-.fi
-.PP
-.SH "ENVIRONMENT"
-.PP
-The \fBcda2dcm\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
-.PP
-The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+\fBdcmencap\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2018-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2018-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcm2cda" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcm2cda" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcm2cda \- Extract CDA file from DICOM encapsulated CDA
.PP
.SH "DESCRIPTION"
.PP
-The \fBdcm2cda\fP utility reads a DICOM file of the Encapsulated CDA Storage SOP Class (\fIdcmfile-in\fP), extracts the embedded CDA document and writes it to an output file (\fIcdafile-out\fP)\&. Optionally a command can be executed after the creation of the CDA file\&.
-.SH "PARAMETERS"
-.PP
-.PP
-.nf
-dcmfile-in DICOM input filename ("-" for stdin)
-
-cdafile-out CDA output filename
-.fi
-.PP
-.SH "OPTIONS"
-.PP
-.SS "general options"
-.PP
-.nf
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-.fi
-.PP
-.SS "input options"
-.PP
-.nf
-input file format:
-
- +f --read-file
- read file format or data set (default)
-
- +fo --read-file-only
- read file format only
-
- -f --read-dataset
- read data set without file meta information
-
-input transfer syntax:
-
- -t= --read-xfer-auto
- use TS recognition (default)
-
- -td --read-xfer-detect
- ignore TS specified in the file meta header
-
- -te --read-xfer-little
- read with explicit VR little endian TS
-
- -tb --read-xfer-big
- read with explicit VR big endian TS
-
- -ti --read-xfer-implicit
- read with implicit VR little endian TS
-
-parsing of odd-length attributes:
-
- +ao --accept-odd-length
- accept odd length attributes (default)
-
- +ae --assume-even-length
- assume real length is one byte larger
-
-handling of undefined length UN elements:
-
- +ui --enable-cp246
- read undefined len UN as implicit VR (default)
-
- -ui --disable-cp246
- read undefined len UN as explicit VR
-
-handling of defined length UN elements:
-
- -uc --retain-un
- retain elements as UN (default)
-
- +uc --convert-un
- convert to real VR if known
-
-automatic data correction:
-
- +dc --enable-correction
- enable automatic data correction (default)
-
- -dc --disable-correction
- disable automatic data correction
-
-bitstream format of deflated input:
-
- +bd --bitstream-deflated
- expect deflated bitstream (default)
-
- +bz --bitstream-zlib
- expect deflated zlib bitstream
-.fi
-.PP
-.SH "LOGGING"
-.PP
-The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
-.PP
-In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
-.SH "EXIT CODES"
-.PP
-The \fBdcm2cda\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
-.SS "general"
-.PP
-.nf
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-.fi
-.PP
-.SS "input file errors"
-.PP
-.nf
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-.fi
-.PP
-.SS "output file errors"
-.PP
-.nf
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-.fi
-.PP
-.SH "COMMAND LINE"
-.PP
-All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
-.PP
-Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
-.PP
-In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
-.SH "ENVIRONMENT"
-.PP
-The \fBdcm2cda\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
-.PP
-The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+The \fBdcm2cda\fP tool is deprecated\&. Use \fBdcmdecap\fP instead, which supports the same command line parameters, and more\&.
.SH "SEE ALSO"
.PP
-\fBcda2dcm\fP(1)
+\fBdcmdecap\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2023-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2023-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcm2img" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcm2img" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcm2img \- Convert DICOM image to standard image format
+cn --conv-never
never convert color space
+bits stored:
+
+ +bs --bits-stored-fix
+ correct inconsistent bits stored value (default)
+
+ # If the value of BitsStored in the compressed bitstream is smaller
+ # than the value in the DICOM dataset, update the value in the dataset
+ # (JPEG compressed images only)
+
+ -bs --bits-stored-keep
+ preserve inconsistent bits stored value
+
+ # Keep the value of BitsStored even if inconsistent with the
+ # compressed bitstream. This may help in correctly decoding some
+ # defective images JPEG compressed images only)
+
workaround options for incorrect encodings (JPEG compressed images only):
+w6 --workaround-pred6
\fBimg2dcm\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2001-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2001-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcm2json" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcm2json" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcm2json \- Convert DICOM file and data set to JSON
-is --is-ds-string
always encode as string
+
+bulk data URI options:
+
+ -b --bulk-disabled
+ write everything as inline binary (default)
+
+ +b --bulk-enabled
+ write large attributes as bulk data
+
+ +bz --bulk-size [s]ize: integer (default: 1)
+ use bulk data for attributes >= s kBytes
+
+ +bp --bulk-uri-prefix [u]ri prefix: string
+ use prefix u when generating bulk data URIs (default: file URI)
+
+ +bd --bulk-dir [d]irectory: string
+ write bulk data files to d (default: '.')
+
+ +bs --bulk-subdir
+ create subdirectory for each SOP instance
+ (default: no subdirectory)
.fi
.PP
.SS "output options"
.fi
.PP
.SS "Bulk Data"
-Binary data, i\&.e\&. DICOM element values with Value Representations (VR) of OB or OW, as well as OD, OF, OL, OV and UN values are always written as 'InlineBinary' (base64 encoding) to the JSON output\&. A future version of this tool might optionally use a 'BulkDataURI' instead, i\&.e\&. the WADO-RS URL of a bulk data item that contains the element value\&. This would be particularly useful for large amounts of data, such as pixel data\&.
+By default, binary data, i\&.e\&. DICOM element values with Value Representations (VR) of OB, OD, OF, OL, OV, OW, and UN values are written as 'InlineBinary' (base64 encoding) to the JSON output\&. Option \fI--bulk-enabled\fP causes binary data as well as DS, FD, FL, IS, SV and UV to be replaced by 'BulkDataURI' values if the element value is larger than the cut-off threshold (default: 1 kByte)\&. The cut-off threshold can be specified with the \fI--bulk-size\fP option\&. The element values themselves are written as files to the directory given by the \fI--bulk-dir\fP option (default: current directory)\&. The filename is based on a SHA-256 checksum of the element value\&. By default, file URIs are generated that point to the bulk directory\&. For production use, a URI prefix for a WADO-RS service over which the element values can be retrieved should be specified using the \fI--bulk-uri-prefix\fP option\&. This can be implemented by configuring a web server that has read access to \fBdcm2json's\fP bulk directory\&. Finally, the option \fI--bulk-subdir\fP will cause a separate subdirectory to be created (and used in the bulk data URI) for each distinct SOP instance\&.
+.PP
+Note that the JSON syntax for the representation of encapsulated pixel data in 'InlineBinary' form is unspecified in DICOM, as is the JSON representation of encapsulated multi-frame pixel data\&. These DICOM files cannot be converted to JSON using \fBdcm2json\fP\&.
+.PP
+The file name extension for the bulk data files generated can be used to determine the MIME type that should be returned by the WADO-RS server:
+.PP
+.PP
+.nf
+ Extension MIME Type
+
+ .bin application/octet-stream
+ .jpeg image/jpeg
+ .dicom-rle image/dicom-rle
+ .jls image/jls
+ .jp2 image/jp2
+ .jpx image/jpx
+ .jphc image/jphc
+ .jxl image/jxl
+ .mpeg video/mpeg
+ .mp4 video/mp4
+ .H265 video/H265
+.fi
+.PP
+.PP
+Finally, it should be noted that bulk data will be written 'as is', i\&.e\&. \fBdcm2json\fP will not attempt to validate or modify the element value in any way\&. For example, \fBdcm2json\fP will not add a JFIF header in the case of JPEG baseline compressed images, which some JPEG viewers may expect\&.
.SH "NOTES"
.PP
.SS "Numbers as Strings"
The DICOM standard allows certain numeric DICOM value representations, DS, IS, SV and UV, to be converted either to a JSON number or a JSON string\&. \fBdcm2json\fP converts DS and IS values to JSON numbers if they are valid decimal strings or integer strings, and to strings if they contain any illegal character\&. \fBdcm2json\fP converts SV and UV values to numbers if they are not larger than 9007199254740991ll or smaller than -9007199254740991ll, and to strings otherwise\&. While the JSON specification permits larger numbers, these are the largest integers that JavaScript can handle\&. Therefore, many JSON parsers cannot process larger numbers\&.
.SS "Character Encoding"
-As required by the DICOM JSON encoding, \fBdcm2json\fP always creates output in Unicode UTF-8 encoding and converts DICOM datasets accordingly\&. If this is not possible, for example because DCMTK has been compiled without character set conversion support, an error is returned\&.
+As required by the DICOM JSON encoding, \fBdcm2json\fP always creates output in Unicode UTF-8 encoding and converts DICOM data sets accordingly\&. If this is not possible, for example because DCMTK has been compiled without character set conversion support, an error is returned\&.
.SH "LOGGING"
.PP
The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
The mapping table files are expected in DCMTK's \fI<datadir>\fP\&. The \fIDCMICONVPATH\fP environment variable can be used to specify a different location\&. If a different location is specified, those mapping tables also replace any built-in tables\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 2016-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2016-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcm2pdf" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcm2pdf" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcm2pdf \- Extract PDF file from DICOM encapsulated PDF
.PP
.SH "DESCRIPTION"
.PP
-The \fBdcm2pdf\fP utility reads a DICOM file of the Encapsulated PDF Storage SOP Class (\fIdcmfile-in\fP), extracts the embedded PDF document and writes it to an output file (\fIpdffile-out\fP)\&. Optionally a command can be executed after the creation of the PDF file\&.
-.SH "PARAMETERS"
-.PP
-.PP
-.nf
-dcmfile-in DICOM input filename ("-" for stdin)
-
-pdffile-out PDF output filename
-.fi
-.PP
-.SH "OPTIONS"
-.PP
-.SS "general options"
-.PP
-.nf
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-.fi
-.PP
-.SS "input options"
-.PP
-.nf
-input file format:
-
- +f --read-file
- read file format or data set (default)
-
- +fo --read-file-only
- read file format only
-
- -f --read-dataset
- read data set without file meta information
-
-input transfer syntax:
-
- -t= --read-xfer-auto
- use TS recognition (default)
-
- -td --read-xfer-detect
- ignore TS specified in the file meta header
-
- -te --read-xfer-little
- read with explicit VR little endian TS
-
- -tb --read-xfer-big
- read with explicit VR big endian TS
-
- -ti --read-xfer-implicit
- read with implicit VR little endian TS
-
-parsing of odd-length attributes:
-
- +ao --accept-odd-length
- accept odd length attributes (default)
-
- +ae --assume-even-length
- assume real length is one byte larger
-
-handling of undefined length UN elements:
-
- +ui --enable-cp246
- read undefined len UN as implicit VR (default)
-
- -ui --disable-cp246
- read undefined len UN as explicit VR
-
-handling of defined length UN elements:
-
- -uc --retain-un
- retain elements as UN (default)
-
- +uc --convert-un
- convert to real VR if known
-
-automatic data correction:
-
- +dc --enable-correction
- enable automatic data correction (default)
-
- -dc --disable-correction
- disable automatic data correction
-
-bitstream format of deflated input:
-
- +bd --bitstream-deflated
- expect deflated bitstream (default)
-
- +bz --bitstream-zlib
- expect deflated zlib bitstream
-.fi
-.PP
-.SS "processing options"
-execution options:
-.PP
-.nf
- -x --exec [c]ommand: string
- execute command c after PDF extraction
-
-.fi
-.PP
-.SH "NOTES"
-.PP
-Option \fI--exec\fP allows for the execution of a certain command line after the creation of the PDF document\&. The command line to be executed is passed to this option as a parameter\&. The specified command line may contain the placeholder '#f', which will be replaced by the PDF filename at run time\&. The specified command line is executed in the foreground, i\&.e\&. \fBpdf2dcm\fP will be blocked until the command terminates\&.
-.SH "LOGGING"
-.PP
-The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
-.PP
-In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
-.SH "EXIT CODES"
-.PP
-The \fBdcm2pdf\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
-.SS "general"
-.PP
-.nf
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-.fi
-.PP
-.SS "input file errors"
-.PP
-.nf
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-.fi
-.PP
-.SS "output file errors"
-.PP
-.nf
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-.fi
-.PP
-.SS "processing errors"
-.PP
-.nf
-EXITCODE_CANNOT_CONVERT_TO_UNICODE 80
-EXITCODE_CANNOT_WRITE_VALID_JSON 81
-.fi
-.PP
-.SH "COMMAND LINE"
-.PP
-All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
-.PP
-Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
-.PP
-In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
-.SH "ENVIRONMENT"
-.PP
-The \fBdcm2pdf\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
-.PP
-The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+The \fBdcm2pdf\fP tool is deprecated\&. Use \fBdcmdecap\fP instead, which supports the same command line parameters, and more\&.
.SH "SEE ALSO"
.PP
-\fBpdf2dcm\fP(1)
+\fBdcmdecap\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2007-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2007-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcm2pnm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcm2pnm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcm2pnm \- Convert DICOM images to PGM/PPM, PNG, TIFF or BMP
\fBdcm2img\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1998-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1998-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcm2xml" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcm2xml" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcm2xml \- Convert DICOM file and data set to XML
\fBxml2dcm\fP(1), \fBdcmconv\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2002-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2002-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmcjpeg" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmcjpeg" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmcjpeg \- Encode DICOM file to JPEG transfer syntax
\fBdcmdjpeg\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2001-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2001-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmcjpls" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmcjpls" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmcjpls \- Encode DICOM file to JPEG-LS transfer syntax
\fBdcmdjpls\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2009-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2009-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmconv" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmconv" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmconv \- Convert DICOM file encoding
\fBdcmdump\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1994-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1994-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmcrle" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmcrle" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmcrle \- Encode DICOM file to RLE transfer syntax
\fBdcmdrle\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2002-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2002-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
--- /dev/null
+.TH "dcmdecap" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
+.nh
+.SH NAME
+dcmdecap \- Extract encapsulated file from DICOM encapsulated storage object
+
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+dcmdecap [options] dcmfile-in encfile-out
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The \fBdcmdecap\fP utility reads a DICOM file of one of the Encapsulated Storage SOP Classes (\fIdcmfile-in\fP), extracts the embedded document and writes it to an output file (\fIencfile-out\fP)\&. Optionally a command can be executed after the creation of the output file\&.
+.SH "PARAMETERS"
+.PP
+.PP
+.nf
+dcmfile-in DICOM input filename ("-" for stdin)
+
+encfile-out Encapsulated document output filename ("-" for stdout)
+.fi
+.PP
+.SH "OPTIONS"
+.PP
+.SS "general options"
+.PP
+.nf
+ -h --help
+ print this help text and exit
+
+ --version
+ print version information and exit
+
+ --arguments
+ print expanded command line arguments
+
+ -q --quiet
+ quiet mode, print no warnings and errors
+
+ -v --verbose
+ verbose mode, print processing details
+
+ -d --debug
+ debug mode, print debug information
+
+ -ll --log-level [l]evel: string constant
+ (fatal, error, warn, info, debug, trace)
+ use level l for the logger
+
+ -lc --log-config [f]ilename: string
+ use config file f for the logger
+.fi
+.PP
+.SS "input options"
+.PP
+.nf
+input file format:
+
+ +f --read-file
+ read file format or data set (default)
+
+ +fo --read-file-only
+ read file format only
+
+ -f --read-dataset
+ read data set without file meta information
+
+input transfer syntax:
+
+ -t= --read-xfer-auto
+ use TS recognition (default)
+
+ -td --read-xfer-detect
+ ignore TS specified in the file meta header
+
+ -te --read-xfer-little
+ read with explicit VR little endian TS
+
+ -tb --read-xfer-big
+ read with explicit VR big endian TS
+
+ -ti --read-xfer-implicit
+ read with implicit VR little endian TS
+
+parsing of odd-length attributes:
+
+ +ao --accept-odd-length
+ accept odd length attributes (default)
+
+ +ae --assume-even-length
+ assume real length is one byte larger
+
+handling of undefined length UN elements:
+
+ +ui --enable-cp246
+ read undefined len UN as implicit VR (default)
+
+ -ui --disable-cp246
+ read undefined len UN as explicit VR
+
+handling of defined length UN elements:
+
+ -uc --retain-un
+ retain elements as UN (default)
+
+ +uc --convert-un
+ convert to real VR if known
+
+automatic data correction:
+
+ +dc --enable-correction
+ enable automatic data correction (default)
+
+ -dc --disable-correction
+ disable automatic data correction
+
+bitstream format of deflated input:
+
+ +bd --bitstream-deflated
+ expect deflated bitstream (default)
+
+ +bz --bitstream-zlib
+ expect deflated zlib bitstream
+.fi
+.PP
+.SS "processing options"
+execution options:
+.PP
+.nf
+ -x --exec [c]ommand: string
+ execute command c after document extraction
+
+.fi
+.PP
+.SH "NOTES"
+.PP
+Option \fI--exec\fP allows for the execution of a certain command line after the creation of the PDF document\&. The command line to be executed is passed to this option as a parameter\&. The specified command line may contain the placeholder '#f', which will be replaced by the output filename at run time\&. The specified command line is executed in the foreground, i\&.e\&. \fBdcmdecap\fP will be blocked until the command terminates\&.
+.SH "LOGGING"
+.PP
+The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
+.PP
+In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
+.SH "EXIT CODES"
+.PP
+The \fBdcmdecap\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
+.SS "general"
+.PP
+.nf
+EXITCODE_NO_ERROR 0
+EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
+.fi
+.PP
+.SS "input file errors"
+.PP
+.nf
+EXITCODE_CANNOT_READ_INPUT_FILE 20
+EXITCODE_NO_INPUT_FILES 21
+EXITCODE_INVALID_INPUT_FILE 22
+.fi
+.PP
+.SS "output file errors"
+.PP
+.nf
+EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
+.fi
+.PP
+.SS "processing errors"
+.PP
+.nf
+EXITCODE_EXEC_FAILED 91
+.fi
+.PP
+.SH "COMMAND LINE"
+.PP
+All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
+.PP
+Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
+.PP
+In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
+.SH "ENVIRONMENT"
+.PP
+The \fBdcmdecap\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
+.PP
+The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+.SH "SEE ALSO"
+.PP
+\fBdcmencap\fP(1)
+.SH "COPYRIGHT"
+.PP
+Copyright (C) 2007-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmdjpeg" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmdjpeg" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmdjpeg \- Decode JPEG-compressed DICOM file
# If the compressed image is a color image, store in color-by-plane
# planar configuration.
+bits stored:
+
+ +bs --bits-stored-fix
+ correct inconsistent bits stored value (default)
+
+ # If the value of BitsStored in the compressed bitstream is smaller
+ # than the value in the DICOM dataset, update the value in the dataset.
+
+ -bs --bits-stored-keep
+ preserve inconsistent bits stored value
+
+ # Keep the value of BitsStored even if inconsistent with the
+ # compressed bitstream. This may help in correctly decoding some
+ # defective images.
+
SOP Instance UID:
+ud --uid-default
\fBdcmcjpeg\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2001-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2001-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmdjpls" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmdjpls" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmdjpls \- Decode JPEG-LS compressed DICOM file
\fBdcmcjpls\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2009-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2009-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmdrle" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmdrle" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmdrle \- Decode RLE-compressed DICOM file
\fBdcmcrle\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2002-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany
+Copyright (C) 2002-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany
-.TH "dcmdspfn" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmdspfn" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmdspfn \- Export standard display curves to a text file
\fBdconvlum\fP(1), \fBdcod2lum\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1999-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1999-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmdump" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmdump" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmdump \- Dump DICOM file and data set
\fBdump2dcm\fP(1), \fBdcmconv\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1994-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1994-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
--- /dev/null
+.TH "dcmencap" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
+.nh
+.SH NAME
+dcmencap \- Encapsulate document into DICOM format
+
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+dcmencap [options] docfile-in dcmfile-out
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The \fBdcmencap\fP utility reads a document file in one of the supported file formats, converts it to a SOP instance of the corresponding DICOM Encapsulated Storage SOP Class and stores the converted data in an output file (\fIdcmfile-out\fP)\&.
+.SH "PARAMETERS"
+.PP
+.PP
+.nf
+docfile-in input filename to be converted
+
+dcmfile-out DICOM output filename ("-" for stdout)
+.fi
+.PP
+.SH "OPTIONS"
+.PP
+.SS "general options"
+.PP
+.nf
+ -h --help
+ print this help text and exit
+
+ --version
+ print version information and exit
+
+ --arguments
+ print expanded command line arguments
+
+ -q --quiet
+ quiet mode, print no warnings and errors
+
+ -v --verbose
+ verbose mode, print processing details
+
+ -d --debug
+ debug mode, print debug information
+
+ -ll --log-level [l]evel: string constant
+ (fatal, error, warn, info, debug, trace)
+ use level l for the logger
+
+ -lc --log-config [f]ilename: string
+ use config file f for the logger
+.fi
+.PP
+.SS "input options"
+.PP
+.nf
+input file format:
+
+ +fa --filetype-auto
+ automatically determine file type (default)
+
+ +fp --filetype-pdf
+ expect PDF file
+
+ +fc --filetype-cda
+ expect CDA file
+
+ +fs --filetype-stl
+ expect STL file
+
+ +fm --filetype-mtl
+ expect MTL file
+
+ +fo --filetype-obj
+ expect OBJ file
+.fi
+.PP
+.SS "DICOM document options"
+.PP
+.nf
+document title:
+
+ +t --title [t]itle: string (default: empty)
+ document title
+
+ +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
+ coded representation of document title defined by coding
+ scheme designator CSD, code value CV and code meaning CM
+
+patient data:
+
+ +pn --patient-name [n]ame: string
+ patient's name in DICOM PN syntax
+
+ +pi --patient-id [i]d: string
+ patient identifier
+
+ +pb --patient-birthdate [d]ate: string (YYYYMMDD)
+ patient's birth date
+
+ +ps --patient-sex [s]ex: string (M, F or O)
+ patient's sex
+
+device data:
+
+ +mn --manufacturer [n]ame: string
+ manufacturer's name
+
+ +mm --manufacturer-model [n]ame: string
+ manufacturer's model name
+
+ +ds --device-serial [n]umber: string
+ device serial number
+
+ +sv --software-versions [v]ersions: string
+ software versions
+
+manufacturing 3d model data (STL/MTL/OBJ only):
+
+ +mu --measurement-units [CSD] [CV] [CM]: string
+ measurement units with coding scheme designator CSD,
+ code value CV and code meaning CM (default: UCUM, um, um)
+
+study and series:
+
+ +sg --generate
+ generate new study and series UIDs (default)
+
+ +st --study-from [f]ilename: string
+ read patient/study data from DICOM file
+
+ +se --series-from [f]ilename: string
+ read patient/study/series data from DICOM file
+
+instance number:
+
+ +i1 --instance-one
+ use instance number 1 (default, not with +se)
+
+ +ii --instance-inc
+ increment instance number (only with +se)
+
+ +is --instance-set [i]nstance number: integer
+ use instance number i
+
+burned-in annotation:
+
+ +an --annotation-yes
+ document contains patient identifying data (default)
+
+ -an --annotation-no
+ document does not contain patient identifying data
+.fi
+.PP
+.SS "processing options"
+.PP
+.nf
+CDA processing options:
+
+ -ov --no-override
+ CDA patient and document data must match study,
+ series or manually entered information (default)
+
+ +ov --override
+ CDA's data will be overwritten by study, series
+ or manually entered information
+
+other processing options:
+
+ -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
+ add further attribute
+.fi
+.PP
+.SS "output options"
+.PP
+.nf
+output transfer syntax:
+ +te --write-xfer-little
+ write with explicit VR little endian (default)
+
+ +tb --write-xfer-big
+ write with explicit VR big endian TS
+
+ +ti --write-xfer-implicit
+ write with implicit VR little endian TS
+
+group length encoding:
+
+ -g --group-length-remove
+ write without group length elements (default)
+
+ +g --group-length-create
+ write with group length elements
+
+length encoding in sequences and items:
+
+ +e --length-explicit
+ write with explicit lengths (default)
+
+ -e --length-undefined
+ write with undefined lengths
+
+data set trailing padding (not with --write-dataset):
+
+ -p --padding-off
+ no padding (implicit if --write-dataset)
+
+ +p --padding-create [f]ile-pad [i]tem-pad: integer
+ align file on multiple of f bytes
+ and items on multiple of i bytes
+.fi
+.PP
+.SH "NOTES"
+.PP
+.SS "Attribute Sources"
+The application may be fed with some additional input for filling mandatory (and optional) attributes in the new DICOM file like patient, study and series information:
+.PP
+.IP "\(bu" 2
+The \fI--key\fP option can be used to add further attributes to the DICOM output file\&.
+.IP "\(bu" 2
+It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&.
+.IP "\(bu" 2
+The \fI--key\fP option can be present more than once\&.
+.IP "\(bu" 2
+The value part (after the '=') may be absent causing the attribute to be set with zero length\&.
+.IP "\(bu" 2
+Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&.
+.PP
+.SH "LOGGING"
+.PP
+The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
+.PP
+In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
+.SH "COMMAND LINE"
+.PP
+All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
+.PP
+Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
+.PP
+In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
+.SH "EXIT CODES"
+.PP
+The \fBdcmencap\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
+.SS "general"
+.PP
+.nf
+EXITCODE_NO_ERROR 0
+.fi
+.PP
+.SS "input file errors"
+.PP
+.nf
+EXITCODE_INVALID_INPUT_FILE 22
+.fi
+.PP
+.SS "output file errors"
+.PP
+.nf
+EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
+.fi
+.PP
+.SH "ENVIRONMENT"
+.PP
+The \fBdcmencap\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
+.PP
+The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+.SH "COPYRIGHT"
+.PP
+Copyright (C) 2018-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmftest" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmftest" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmftest \- Test if file uses DICOM part 10 format
\fBdcmgpdir\fP(1), \fBdcmmkdir\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1997-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1997-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmgpdir" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmgpdir" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmgpdir \- Create a general purpose DICOMDIR
\fBdcmmkdir\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1996-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1996-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmicmp" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmicmp" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmicmp \- Compare DICOM images and compute difference metrics
\fBdcm2pnm\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2018-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2018-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmj2pnm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmj2pnm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmj2pnm \- Convert DICOM images to PGM/PPM, PNG, TIFF, JPEG or BMP
\fBdcm2img\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2001-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2001-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcml2pnm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcml2pnm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcml2pnm \- Convert DICOM images to PGM/PPM, PNG, TIFF or BMP
\fBdcm2img\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2001-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2001-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmmkcrv" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmmkcrv" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmmkcrv \- Add 2D curve data to image
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 1998-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1998-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmmkdir" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmmkdir" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmmkdir \- Create a DICOMDIR file
\fBdcmgpdir\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2001-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2001-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmmklut" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmmklut" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmmklut \- Create DICOM look-up tables
\fI<datadir>/philips\&.lut\fP - sample LUT in text format
.SH "COPYRIGHT"
.PP
-Copyright (C) 1998-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1998-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmodify" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmodify" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmodify \- Modify DICOM files
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 2003-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2003-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmp2pgm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmp2pgm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmp2pgm \- Read DICOM image and presentation state and render bitmap
\fI<etcdir>/dcmpstat\&.cfg\fP - sample configuration file
.SH "COPYRIGHT"
.PP
-Copyright (C) 1998-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1998-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmprscp" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmprscp" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmprscp \- DICOM basic grayscale print management SCP
\fBdcmprscu\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1999-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1999-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmprscu" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmprscu" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmprscu \- Print spooler for presentation state viewer
\fBdcmprscp\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1999-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1999-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmpschk" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmpschk" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmpschk \- Checking tool for presentation states
use config file f for the logger
.fi
.PP
+.SS "validation options"
+.PP
+.nf
+ --validate-std
+ images referenced by GSPS must belong to the
+ same SOP class (default)
+
+ --validate-related
+ images referenced by GSPS may belong to related
+ 'for presentation' and 'for processing' SOP class
+
+ --validate-relaxed
+ images referenced by GSPS may be any SOP class
+.fi
+.PP
.SH "LOGGING"
.PP
The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 2000-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2000-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmpsmk" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmpsmk" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmpsmk \- Create DICOM grayscale softcopy presentation state
image located on storage medium
.fi
.PP
+.SS "validation options"
+.PP
+.nf
+ --validate-std
+ images referenced by GSPS must belong to the
+ same SOP class (default)
+
+ --validate-related
+ images referenced by GSPS may belong to related
+ 'for presentation' and 'for processing' SOP class
+
+ --validate-relaxed
+ images referenced by GSPS may be any SOP class
+.fi
+.PP
.SS "output options"
.PP
.nf
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 1998-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1998-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmpsprt" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmpsprt" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmpsprt \- Read DICOM images and presentation states and render print job
\fBdcmprscu\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1999-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1999-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmpsrcv" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmpsrcv" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmpsrcv \- Network receive for presentation state viewer
\fBdcmpssnd\fP(1), \fBstorescp\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1998-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1998-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmpssnd" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmpssnd" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmpssnd \- Network send for presentation state viewer
\fBdcmpsrcv\fP(1), \fBstorescu\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1998-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1998-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmqridx" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmqridx" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmqridx \- Register a DICOM image file in an image database index file
\fBdcmqrscp\fP(1), \fBdcmqrti\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1993-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1993-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmqrscp" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmqrscp" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmqrscp \- DICOM image archive (central test node)
.SS "network options"
.PP
.nf
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
association negotiation profiles from configuration file:
-xf --assoc-config-file
ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3
SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4
BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
DICONDE_EddyCurrentMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.601.2
DICONDE_ThermographyImageStorage 1.2.840.10008.5.1.4.1.1.601.3
DICONDE_ThermographyMultiFrameImageStorage 1.2.840.10008.5.1.4.1.1.601.4
+DICONDE_UltrasoundWaveformStorage 1.2.840.10008.5.1.4.1.1.601.5
DRAFT_RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.1
RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.7
RTBrachyApplicationSetupDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.10
(0010,0040) PatientSex
(0010,1000) OtherPatientIDs (retired)
(0010,1001) OtherPatientNames
-(0010,2160) EthnicGroup
+(0010,2160) EthnicGroup (retired)
(0010,4000) PatientComments
.fi
.PP
(0010,21B0) AdditionalPatientHistory
(0020,000D) StudyInstanceUID
(0020,0010) StudyID
-(0020,1070) RETIRED_OtherStudyNumbers
+(0020,1070) OtherStudyNumbers (retired)
.fi
.PP
.PP
\fBdcmqridx\fP(1), \fBdcmqrti\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1993-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1993-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmqrti" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmqrti" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmqrti \- The Terminal Initiator Telnet Client Program
\fBdcmqrscp\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1993-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1993-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmquant" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmquant" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmquant \- Convert DICOM color images to palette color
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 2001-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2001-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmrecv" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmrecv" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmrecv \- Simple DICOM storage SCP (receiver)
.SS "network options"
.PP
.nf
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
association negotiation profile from configuration file:
-xf --config-file [f]ilename, [p]rofile: string
\fBdcmsend\fP(1), \fBstorescu\fP(1), \fBstorescp\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2013-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2013-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmscale" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmscale" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmscale \- Scale DICOM images
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 2002-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2002-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmsend" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmsend" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmsend \- Simple DICOM storage SCU (sender)
\fBdcmrecv\fP(1), \fBstorescu\fP(1), \fBstorescp\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2011-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2011-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcmsign" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcmsign" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcmsign \- Sign and Verify DICOM Files
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 2000-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2000-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dcod2lum" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dcod2lum" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dcod2lum \- Convert hardcopy characteristic curve file to softcopy format
\fBdcmdspfn\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2002-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2002-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dconvlum" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dconvlum" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dconvlum \- Convert VeriLUM files to DCMTK display files
\fBdcmdspfn\fP(1), \fBdcm2pnm\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1999-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1999-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "drtdump" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "drtdump" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
drtdump \- Dump DICOM RT file and data set
\fBdcmconv\fP(1), \fBdcmdump\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2010-2024 by OFFIS e\&.V\&. and ICSMED AG, Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2010-2025 by OFFIS e\&.V\&. and ICSMED AG, Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dsr2html" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dsr2html" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dsr2html \- Render DICOM SR file and data set to HTML/XHTML
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
.fi
.PP
+.PP
+(*) This is not a Storage SOP Class, but used for Real-Time Communication\&.
.SS "Character Encoding"
The HTML/XHTML encoding is determined automatically from the DICOM attribute (0008,0005) 'Specific Character Set' using the following mapping:
.PP
If this DICOM attribute is missing in the input file, although needed, option \fI--charset-assume\fP can be used to specify an appropriate character set manually (using one of the DICOM defined terms)\&. For reasons of backward compatibility with previous versions of this tool, the following terms are also supported and mapped automatically to the associated DICOM defined terms: latin-1, latin-2, latin-3, latin-4, latin-5, latin-9, cyrillic, arabic, greek, hebrew\&.
.PP
Option \fI--convert-to-utf8\fP can be used to convert the DICOM file or data set to UTF-8 encoding prior to the rendering to HTML/XHTML format\&.
+.SS "Security"
+Please note that using one of the options \fI--css-reference\fP, \fI--css-file\fP or \fI--hyperlink-url-prefix\fP can lead to security issues, as an attacker could misuse them to potentially inject dangerous content into the HTML/XHTML output\&. The values passed to these options are not checked, neither the URL and prefix nor the content of the specified CSS file\&.
.SH "LOGGING"
.PP
The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
The mapping table files are expected in DCMTK's \fI<datadir>\fP\&. The \fIDCMICONVPATH\fP environment variable can be used to specify a different location\&. If a different location is specified, those mapping tables also replace any built-in tables\&.
.SH "FILES"
.PP
-\fI<datadir>/report\&.css\fP - Sample Cascading Stylesheet file for HTML \fI<datadir>/reportx\&.css\fP - Sample Cascading Stylesheet file for XHTML
+\fI<datadir>/report\&.css\fP - Sample Cascading Stylesheet file for HTML
+.br
+\fI<datadir>/reportx\&.css\fP - Sample Cascading Stylesheet file for XHTML
.SH "SEE ALSO"
.PP
\fBdcmconv\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2000-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2000-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dsr2xml" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dsr2xml" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dsr2xml \- Convert DICOM SR file and data set to XML
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
.fi
.PP
.PP
+(*) This is not a Storage SOP Class, but used for Real-Time Communication\&.
+.PP
Please note that currently only mandatory and some optional attributes are supported\&.
.SS "Character Encoding"
The XML encoding is determined automatically from the DICOM attribute (0008,0005) 'Specific Character Set' using the following mapping:
\fBxml2dsr\fP(1), \fBdcmconv\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2000-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2000-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dsrdump" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dsrdump" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dsrdump \- Dump DICOM SR file and data set
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
.fi
.PP
+.PP
+(*) This is not a Storage SOP Class, but used for Real-Time Communication\&.
.SH "LOGGING"
.PP
The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
\fBdcmconv\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2000-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2000-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "dump2dcm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "dump2dcm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
dump2dcm \- Convert ASCII dump to DICOM file
\fBdcmdump\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1996-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1996-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "echoscu" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "echoscu" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
echoscu \- DICOM verification (C-ECHO) SCU
association negotiation debugging:
- -pts --propose-ts [n]umber: integer (1..52)
+ -pts --propose-ts [n]umber: integer (1..53)
propose n transfer syntaxes
-ppc --propose-pc [n]umber: integer (1..128)
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 1994-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1994-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "findscu" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "findscu" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
findscu \- DICOM query (C-FIND) SCU
\fBmovescu\fP(1), \fBdump2dcm\fP(1), \fBdcmodify\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1994-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1994-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "getscu" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "getscu" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
getscu \- DICOM retrieve (C-GET) SCU
GeneralAudioWaveformStorage 1.2.840.10008.5.1.4.1.1.9.4.2
ArterialPulseWaveformStorage 1.2.840.10008.5.1.4.1.1.9.5.1
RespiratoryWaveformStorage 1.2.840.10008.5.1.4.1.1.9.6.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
\fBfindscu\fP(1), \fBmovescu\fP(1), \fBdump2dcm\fP(1), \fBdcmodify\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2011-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2011-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "img2dcm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "img2dcm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
img2dcm \- Convert standard image formats into DICOM format
.PP
For DICOM it is clear that SPIFF header should not be present in the DICOM object's internal JPEG-LS stream\&. The plugin will simply rejects any input JPEG-LS file containing a SPIFF header at marker APP8\&.
.PP
-By default, all APPn markers are cut off from the original JPEG-LS stream\&. However, if you want to keep APPn markers (e\&.g\&. APP8/HP color transform information, aka 'mrfx') inside the DICOM stream, the option \fI--keep-appn\fP does the trick\&. Pay attention that the plugin will check the actual color transform specified in the APP8/HP marker\&. Since DICOM does not allow any color transform to be specified in the APP8 marker, only a value of \fC0\fP (no color transform) is accepted\&.
+By default, all APPn markers are cut off from the original JPEG-LS stream\&. However, if you want to keep APPn markers (e\&.g\&. APP8/HP color transform information, aka 'mrfx') inside the DICOM stream, the option \fI--keep-appn\fP does the trick\&. Pay attention that the plugin will check the actual color transform specified in the APP8/HP marker\&. Since DICOM does not allow any color transform to be specified in the APP8 marker, only a value of 0 (no color transform) is accepted\&.
.SS "BMP Input Plugin"
\fBimg2dcm\fP supports BMP as input format\&. However, so far only the most common BMP images are supported\&. In particular, BMP images which use bit fields or run length encoding will be rejected\&. Such images are uncommon\&. Input images will either be converted into a DICOM image with RGB color model and a bit depth of 24, or into an image with MONOCHROME2 color model an 8 bits per pixel\&. There are no specific options for fine-tuning BMP format conversion\&.
.SS "Output Plugins"
\fBdcm2pnm\fP(1), \fBdcmj2pnm\fP(1), \fBdump2dcm\fP(1), \fBdcmconv\fP(1), \fBdcmodify\fP(1), \fBdcm2xml\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2007-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2007-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
--- /dev/null
+.TH "json2dcm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
+.nh
+.SH NAME
+json2dcm \- Convert JSON document to DICOM file or data set
+
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+json2dcm [options] jsonfile-in dcmfile-out
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+The \fBjson2dcm\fP utility converts the contents of a JSON (JavaScript Object Notation) document to a binary DICOM file or data set\&. The JSON document is expected to conform to the 'DICOM JSON Model' as defined in DICOM Part 18 Section F\&. Such JSON files can be created, e\&.g\&., using the \fBdcm2json\fP tool\&.
+.SH "PARAMETERS"
+.PP
+.PP
+.nf
+jsonfile-in JSON input filename to be converted ("-" for stdin)
+
+dcmfile-out DICOM output filename ("-" for stdout)
+.fi
+.PP
+.SH "OPTIONS"
+.PP
+.SS "general options"
+.PP
+.nf
+ -h --help
+ print this help text and exit
+
+ --version
+ print version information and exit
+
+ --arguments
+ print expanded command line arguments
+
+ -q --quiet
+ quiet mode, print no warnings and errors
+
+ -v --verbose
+ verbose mode, print processing details
+
+ -d --debug
+ debug mode, print debug information
+
+ -ll --log-level [l]evel: string constant
+ (fatal, error, warn, info, debug, trace)
+ use level l for the logger
+
+ -lc --log-config [f]ilename: string
+ use config file f for the logger
+.fi
+.PP
+.SS "input options"
+.PP
+.nf
+input file format:
+
+ +f --read-meta-info
+ read meta information if present (default)
+
+ -f --ignore-meta-info
+ ignore file meta information
+.fi
+.PP
+.SS "processing options"
+.PP
+.nf
+unique identifiers:
+
+ +Ug --generate-new-uids
+ generate new Study/Series/SOP Instance UID
+
+ -Uo --dont-overwrite-uids
+ do not overwrite existing UIDs (default)
+
+ +Uo --overwrite-uids
+ overwrite existing UIDs
+
+bulkdata URI handling:
+
+ +Bu --parse-bulkdata-uri
+ parse Bulkdata URIs (default)
+
+ -Bu --ignore-bulkdata-uri
+ ignore Bulkdata URIs
+
+ +Bd --add-bulkdata-dir [d]irectory: string
+ add d to list of permitted bulk data sources
+
+handling of arrays with multiple data sets:
+
+ -ar --array-reject
+ reject multiple data sets (default)
+
+ +as --array-select [n]umber: integer
+ select data set n from array
+
+ +ar --array-sequence
+ store all data sets in private sequence
+.fi
+.PP
+.SS "output options"
+.PP
+.nf
+output file format:
+
+ +F --write-file
+ write file format (default)
+
+ -F --write-dataset
+ write data set without file meta information
+
+ +Fu --update-meta-info
+ update particular file meta information
+
+output transfer syntax:
+
+ +t= --write-xfer-same
+ write with same TS as input (default)
+
+ +te --write-xfer-little
+ write with explicit VR little endian TS
+
+ +tb --write-xfer-big
+ write with explicit VR big endian TS
+
+ +ti --write-xfer-implicit
+ write with implicit VR little endian TS
+
+ +td --write-xfer-deflated
+ write with deflated explicit VR little endian TS
+
+error handling:
+
+ -E --stop-on-error
+ do not write if document is invalid (default)
+
+ +E --ignore-errors
+ attempt to write even if document is invalid
+
+post-1993 value representations:
+
+ +u --enable-new-vr
+ enable support for new VRs (UN/UT) (default)
+
+ -u --disable-new-vr
+ disable support for new VRs, convert to OB
+
+length encoding in sequences and items:
+
+ +e --length-explicit
+ write with explicit lengths (default)
+
+ -e --length-undefined
+ write with undefined lengths
+
+charset handling:
+
+ +c --charset-accept
+ write with the given charset in JSON (default)
+
+ -c --charset-replace
+ replace the given charset in JSON with UTF-8
+
+deflate compression level (only with --write-xfer-deflated):
+
+ +cl --compression-level [l]evel: integer (default: 6)
+ 0=uncompressed, 1=fastest, 9=best compression
+.fi
+.PP
+.SH "NOTES"
+.PP
+The basic structure of the JSON input expected looks like the following (see DICOM Part 18 Section F for details):
+.PP
+.PP
+.nf
+{
+ "00080005": {
+ "vr": "CS",
+ "Value": [
+ "ISO_IR 192"
+ ]
+ },
+ "00080020": {
+ "vr": "DT",
+ "Value": [
+ "20130409"
+ ]
+ },
+ "00080030": {
+ "vr": "TM",
+ "Value": [
+ "131600.0000"
+ ]
+ },
+ "00080050": {
+ "vr": "SH",
+ "Value": [
+ "11235813"
+ ]
+ },
+ "00080056": {
+ "vr": "CS",
+ "Value": [
+ "ONLINE"
+ ]
+ },
+ "00080061": {
+ "vr": "CS",
+ "Value": [
+ "CT",
+ "PET"
+ ]
+ },
+ "00080090": {
+ "vr": "PN",
+ "Value": [
+ {
+ "Alphabetic": "^Bob^^Dr."
+ }
+ ]
+ },
+ "00081190": {
+ "vr": "UR",
+ "Value": [
+ "http://wado.nema.org/studies/
+ 1.2.392.200036.9116.2.2.2.1762893313.1029997326.945873"
+ ]
+ },
+ "00090010": {
+ "vr": "LO",
+ "Value": [
+ "Vendor A"
+ ]
+ },
+ "00091002": {
+ "vr": "UN",
+ "InlineBinary": "z0x9c8v7"
+ },
+ "00100010": {
+ "vr": "PN",
+ "Value": [
+ {
+ "Alphabetic": "Wang^XiaoDong"
+ }
+ ]
+ },
+ "00100020": {
+ "vr": "LO",
+ "Value": [
+ "12345"
+ ]
+ },
+ "00100021": {
+ "vr": "LO",
+ "Value": [
+ "Hospital A"
+ ]
+ },
+ "00100030": {
+ "vr": "DA",
+ "Value": [
+ "19670701"
+ ]
+ },
+ "00100040": {
+ "vr": "CS",
+ "Value": [
+ "M"
+ ]
+ },
+ "00101002": {
+ "vr": "SQ",
+ "Value": [
+ {
+ "00100020": {
+ "vr": "LO",
+ "Value": [
+ "54321"
+ ]
+ },
+ "00100021": {
+ "vr": "LO",
+ "Value": [
+ "Hospital B"
+ ]
+ }
+ },
+ {
+ "00100020": {
+ "vr": "LO",
+ "Value": [
+ "24680"
+ ]
+ },
+ "00100021": {
+ "vr": "LO",
+ "Value": [
+ "Hospital C"
+ ]
+ }
+ }
+ ]
+ },
+ "0020000D": {
+ "vr": "UI",
+ "Value": [
+ "1.2.392.200036.9116.2.2.2.1762893313.1029997326.945873"
+ ]
+ },
+ "00200010": {
+ "vr": "SH",
+ "Value": [
+ "11235813"
+ ]
+ },
+ "00201206": {
+ "vr": "IS",
+ "Value": [
+ 4
+ ]
+ },
+ "00201208": {
+ "vr": "IS",
+ "Value": [
+ 942
+ ]
+ }
+}
+.fi
+.PP
+.SS "Character Encoding"
+The JSON format only supports UTF-8 encoding\&. Thus the generated DICOM file will also contain UTF-8 encoding\&. If the JSON file does not contain a specific character set, or a specific character set other than 'ISO_IR 192', a warning will be issued\&.
+.SS "Binary Data, Bulk Data, and Pixel Data"
+The DICOM JSON Model uses 'InlineBinary' to store attribute values of binary value representations such as 'OB', 'OW', 'OD', 'OF', 'OL', 'OV' etc\&. in Base64 encoded form\&. This is supported in \fBjson2dcm\fP for all binary attributes, including unencapsulated pixel data\&.
+.PP
+The DICOM JSON Model also permits attribute values to be stored separately from the JSON data set and to be referenced through a BulkDataURI\&. This is supported for file URIs that reference files in the local filesystem\&. \fBjson2dcm\fP tool also supports the inofficial extension to the file URI scheme generated by \fIDCM4CHE\fP, where parameters named 'offset' and 'length' are appended to the file URI in order to refer to a specific part of a file\&. HTTP URIs as well as URIs that identify another part in a MIME multipart/related structure are not yet supported in \fBjson2dcm\fP\&. If the command line option \fI--ignore-bulkdata-uri\fP is specified, then all bulk data URIs are ignored and attributes with bulk data will be written with empty value\&.
+.PP
+Finally, encapsulated (in particular, compressed) pixel data is not supported by \fBjson2dcm\fP because the syntax of the DICOM JSON Model for this specific case is not defined in the DICOM standard yet\&.
+.SS "Arrays of Data Sets"
+The DICOM JSON Model uses a JSON array structure to return multiple data sets in DICOMweb services such as WADO-RS or QIDO-RS\&. JSON arrays containing a single DICOM data set are automatically recognized by \fBjson2dcm\fP and treated like a data set without the surrounding array structure\&. JSON arrays containing multiple data sets are rejected by default\&. Alternatively, the \fI--array-select\fP option can be used to select one data set from the array to be converted\&. The \fI--array-sequence\fP option causes all data sets to be written as sequence items into a single private sequence with attribute tag (0009,1000)\&. Such files, which are mostly intended for debugging purposes, can be recognized by the private creator element (0009,0010), which has the value 'JSON2DCM_LIST_OF_DATASETS'\&.
+.SS "Trailing Commas"
+Trailing commas are not permitted in JSON, but \fBjson2dcm\fP will still accept such JSON data sets without warning or error message because they are handled gracefully by the underlying JSON parser\&. Users should, therefore, not assume that a JSON data set is valid just because \fBjson2dcm\fP accepts it\&. This tool is not designed as a validator for JSON or the DICOM JSON Model\&.
+.SH "LOGGING"
+.PP
+The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
+.PP
+In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
+.SH "COMMAND LINE"
+.PP
+All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
+.PP
+Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
+.PP
+In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
+.SH "EXIT CODES"
+.PP
+The \fBdcm2json\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
+.SS "general"
+.PP
+.nf
+EXITCODE_NO_ERROR 0
+EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
+.fi
+.PP
+.SS "input file errors"
+.PP
+.nf
+EXITCODE_CANNOT_READ_INPUT_FILE 20
+.fi
+.PP
+.SS "output file errors"
+.PP
+.nf
+EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
+.fi
+.PP
+.SS "processing errors"
+.PP
+.nf
+EXITCODE_INVALID_JSON_CONTENT 65
+EXITCODE_BULKDATA_URI_NOT_SUPPORTED 66
+.fi
+.PP
+.SH "ENVIRONMENT"
+.PP
+The \fBjson2dcm\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
+.PP
+The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+.SH "SEE ALSO"
+.PP
+\fBdcm2json\fP(1) \fBdump2dcm\fP(2)
+.SH "COPYRIGHT"
+.PP
+Copyright (C) 2024-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "mkcsmapper" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "mkcsmapper" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
mkcsmapper \- Create csmapper conversion files for oficonv
-.TH "mkesdb" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "mkesdb" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
mkesdb \- Create encoding scheme database (esdb) files for oficonv
-.TH "movescu" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "movescu" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
movescu \- DICOM retrieve (C-MOVE) SCU
.SS "network options"
.PP
.nf
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
override matching keys:
-k --key [k]ey: gggg,eeee="str" or dictionary name="str"
silently correct space-padded UIDs
.fi
.PP
+.SS "transport layer security (TLS) options"
+.PP
+.nf
+transport protocol stack:
+
+ -tls --disable-tls
+ use normal TCP/IP connection (default)
+
+ +tls --enable-tls [p]rivate key file, [c]ertificate file: string
+ use authenticated secure TLS connection
+
+private key password (only with --enable-tls):
+
+ +ps --std-passwd
+ prompt user to type password on stdin (default)
+
+ +pw --use-passwd [p]assword: string
+ use specified password
+
+ -pw --null-passwd
+ use empty string as password
+
+key and certificate file format:
+
+ -pem --pem-keys
+ read keys and certificates as PEM file (default)
+
+ -der --der-keys
+ read keys and certificates as DER file
+
+certification authority:
+
+ +cf --add-cert-file [f]ilename: string
+ add certificate file to list of certificates
+
+ +cd --add-cert-dir [d]irectory: string
+ add certificates in d to list of certificates
+
+ +crl --add-crl-file [f]ilename: string
+ add certificate revocation list file
+ (implies --enable-crl-vfy)
+
+ +crv --enable-crl-vfy
+ enable leaf CRL verification
+
+ +cra --enable-crl-all
+ enable full chain CRL verification
+
+security profile:
+
+ +ph --list-profiles
+ list supported TLS profiles and exit
+
+ +pg --profile-8996
+ BCP 195 RFC 8996 TLS Profile (default)
+
+ +pm --profile-8996-mod
+ Modified BCP 195 RFC 8996 TLS Profile
+
+ # only available if underlying TLS library supports
+ # all TLS features required for this profile
+
+ +py --profile-bcp195-nd
+ Non-downgrading BCP 195 TLS Profile (retired)
+
+ +px --profile-bcp195
+ BCP 195 TLS Profile (retired)
+
+ +pz --profile-bcp195-ex
+ Extended BCP 195 TLS Profile (retired)
+
+ +pb --profile-basic
+ Basic TLS Secure Transport Connection Profile (retired)
+
+ # only available if underlying TLS library supports 3DES
+
+ +pa --profile-aes
+ AES TLS Secure Transport Connection Profile (retired)
+
+ +pn --profile-null
+ Authenticated unencrypted communication
+ (retired, was used in IHE ATNA)
+
+ciphersuite:
+
+ +cc --list-ciphers
+ list supported TLS ciphersuites and exit
+
+ +cs --cipher [c]iphersuite name: string
+ add ciphersuite to list of negotiated suites
+
+ +dp --dhparam [f]ilename: string
+ read DH parameters for DH/DSS ciphersuites
+
+server name indication:
+
+ --no-sni
+ do not use SNI (default)
+
+ --expect-sni [s]erver name: string
+ expect requests for server name s
+
+pseudo random generator:
+
+ +rs --seed [f]ilename: string
+ seed random generator with contents of f
+
+ +ws --write-seed
+ write back modified seed (only with --seed)
+
+ +wf --write-seed-file [f]ilename: string (only with --seed)
+ write modified seed to file f
+
+peer authentication:
+
+ -rc --require-peer-cert
+ verify peer certificate, fail if absent (default)
+
+ -vc --verify-peer-cert
+ verify peer certificate if present
+
+ -ic --ignore-peer-cert
+ don't verify peer certificate
+.fi
+.PP
.SS "output options"
.PP
.nf
ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3
SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4
BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
DICONDE_EddyCurrentMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.601.2
DICONDE_ThermographyImageStorage 1.2.840.10008.5.1.4.1.1.601.3
DICONDE_ThermographyMultiFrameImageStorage 1.2.840.10008.5.1.4.1.1.601.4
+DICONDE_UltrasoundWaveformStorage 1.2.840.10008.5.1.4.1.1.601.5
DRAFT_RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.1
RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.7
RTBrachyApplicationSetupDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.10
HighThroughputJPEG2000RPCLImageCompressionLoss.Tr.S. 1.2.840.10008.1.2.4.202
HighThroughputJPEG2000ImageCompressionTransferSynta. 1.2.840.10008.1.2.4.203
RLELosslessTransferSyntax 1.2.840.10008.1.2.5
+DeflatedImageFrameCompressionTransferSyntax 1.2.840.10008.1.2.8.1
.fi
.PP
.PP
EXITCODE_CANNOT_CLOSE_ASSOCIATION 67
EXITCODE_CMOVE_WARNING 68
EXITCODE_CMOVE_ERROR 69
+EXITCODE_CANNOT_CREATE_TLS_LAYER 70
.fi
.PP
.SH "ENVIRONMENT"
\fBfindscu\fP(1), \fBstorescp\fP(1), \fBdump2dcm\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1994-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1994-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "pdf2dcm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "pdf2dcm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
pdf2dcm \- Encapsulate PDF file into DICOM file format
.PP
.SH "DESCRIPTION"
.PP
-The \fBpdf2dcm\fP utility reads a PDF file (\fIpdffile-in\fP), converts it to a DICOM Encapsulated PDF Storage SOP instance and stores the converted data to an output file (\fIdcmfile-out\fP)\&.
-.SH "PARAMETERS"
-.PP
-.PP
-.nf
-pdffile-in PDF input filename to be encapsulated
-
-dcmfile-out DICOM output filename ("-" for stdout)
-.fi
-.PP
-.SH "OPTIONS"
-.PP
-.SS "general options"
-.PP
-.nf
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-.fi
-.PP
-.SS "DICOM document options"
-.PP
-.nf
-document title:
-
- +t --title [t]itle: string (default: empty)
- document title
-
- +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
- coded representation of document title defined by coding
- scheme designator CSD, code value CV and code meaning CM
-
-patient data:
-
- +pn --patient-name [n]ame: string
- patient's name in DICOM PN syntax
-
- +pi --patient-id [i]d: string
- patient identifier
-
- +pb --patient-birthdate [d]ate: string (YYYYMMDD)
- patient's birth date
-
- +ps --patient-sex [s]ex: string (M, F or O)
- patient's sex
-
-study and series:
-
- +sg --generate
- generate new study and series UIDs (default)
-
- +st --study-from [f]ilename: string
- read patient/study data from DICOM file
-
- +se --series-from [f]ilename: string
- read patient/study/series data from DICOM file
-
-instance number:
-
- +i1 --instance-one
- use instance number 1 (default, not with +se)
-
- +ii --instance-inc
- increment instance number (only with +se)
-
- +is --instance-set [i]nstance number: integer
- use instance number i
-
-burned-in annotation:
-
- +an --annotation-yes
- document contains patient identifying data (default)
-
- -an --annotation-no
- document does not contain patient identifying data
-.fi
-.PP
-.SS "processing options"
-.PP
-.nf
-other processing options:
-
- -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
- add further attribute
-.fi
-.PP
-.SS "output options"
-.PP
-.nf
-output file format:
-
- +F --write-file
- write file format (default)
-
- -F --write-dataset
- write data set without file meta information
-
-group length encoding:
-
- +g= --group-length-recalc
- recalculate group lengths if present (default)
-
- +g --group-length-create
- always write with group length elements
-
- -g --group-length-remove
- always write without group length elements
-
-length encoding in sequences and items:
-
- +e --length-explicit
- write with explicit lengths (default)
-
- -e --length-undefined
- write with undefined lengths
-
-data set trailing padding (not with --write-dataset):
-
- -p --padding-off
- no padding (implicit if --write-dataset)
-
- +p --padding-create [f]ile-pad [i]tem-pad: integer
- align file on multiple of f bytes
- and items on multiple of i bytes
-.fi
-.PP
-.SH "NOTES"
-.PP
-.SS "Attribute Sources"
-The application may be fed with some additional input for filling mandatory (and optional) attributes in the new DICOM file like patient, study and series information:
-.PP
-.IP "\(bu" 2
-The \fI--key\fP option can be used to add further attributes to the DICOM output file\&.
-.IP "\(bu" 2
-It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&.
-.IP "\(bu" 2
-The \fI--key\fP option can be present more than once\&.
-.IP "\(bu" 2
-The value part (after the '=') may be absent causing the attribute to be set with zero length\&.
-.IP "\(bu" 2
-Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&.
-.PP
-.SH "LOGGING"
-.PP
-The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
-.PP
-In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
-.SH "COMMAND LINE"
-.PP
-All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
-.PP
-Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
-.PP
-In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
-.SH "EXIT CODES"
-.PP
-The \fBpdf2dcm\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
-.SS "general"
-.PP
-.nf
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-EXITCODE_MEMORY_EXHAUSTED 4
-.fi
-.PP
-.SS "input file errors"
-.PP
-.nf
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-.fi
-.PP
-.SS "output file errors"
-.PP
-.nf
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-.fi
-.PP
-.SH "ENVIRONMENT"
-.PP
-The \fBpdf2dcm\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
-.PP
-The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+The \fBpdf2dcm\fP tool is deprecated\&. Use \fBdcmencap\fP instead, which supports the same command line parameters, and more\&.
.SH "SEE ALSO"
.PP
-\fBdcm2pdf\fP(1)
+\fBdcmencap\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2005-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2005-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "stl2dcm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "stl2dcm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
stl2dcm \- Encapsulate STL file into DICOM file format
.PP
.SH "DESCRIPTION"
.PP
-The \fBstl2dcm\fP utility reads a STL file (\fIstlfile-in\fP), converts it to a DICOM Encapsulated STL Storage SOP instance and stores the converted data to an output file (\fIdcmfile-out\fP)\&.
-.SH "PARAMETERS"
+The \fBstl2dcm\fP tool is deprecated\&. Use \fBdcmencap\fP instead, which supports the same command line parameters, and more\&.
+.SH "SEE ALSO"
.PP
-.PP
-.nf
-stlfile-in STL input filename to be encapsulated
-
-dcmfile-out DICOM output filename ("-" for stdout)
-.fi
-.PP
-.SH "OPTIONS"
-.PP
-.SS "general options"
-.PP
-.nf
- -h --help
- print this help text and exit
-
- --version
- print version information and exit
-
- --arguments
- print expanded command line arguments
-
- -q --quiet
- quiet mode, print no warnings and errors
-
- -v --verbose
- verbose mode, print processing details
-
- -d --debug
- debug mode, print debug information
-
- -ll --log-level [l]evel: string constant
- (fatal, error, warn, info, debug, trace)
- use level l for the logger
-
- -lc --log-config [f]ilename: string
- use config file f for the logger
-.fi
-.PP
-.SS "DICOM document options"
-.PP
-.nf
-document title:
-
- +t --title [t]itle: string (default: empty)
- document title
-
- +cn --concept-name [CSD] [CV] [CM]: string (default: empty)
- coded representation of document title defined by coding
- scheme designator CSD, code value CV and code meaning CM
-
-patient data:
-
- +pn --patient-name [n]ame: string
- patient's name in DICOM PN syntax
-
- +pi --patient-id [i]d: string
- patient identifier
-
- +pb --patient-birthdate [d]ate: string (YYYYMMDD)
- patient's birth date
-
- +ps --patient-sex [s]ex: string (M, F or O)
- patient's sex
-
-study and series:
-
- +sg --generate
- generate new study and series UIDs (default)
-
- +st --study-from [f]ilename: string
- read patient/study data from DICOM file
-
- +se --series-from [f]ilename: string
- read patient/study/series data from DICOM file
-
-instance number:
-
- +i1 --instance-one
- use instance number 1 (default, not with +se)
-
- +ii --instance-inc
- increment instance number (only with +se)
-
- +is --instance-set [i]nstance number: integer
- use instance number i
-
-burned-in annotation:
-
- +an --annotation-yes
- document contains patient identifying data (default)
-
- -an --annotation-no
- document does not contain patient identifying data
-
-enhanced general equipment:
-
- +mn --manufacturer [n]ame: string
- manufacturer's name
-
- +mm --manufacturer-model [n]ame: string
- manufacturer's model name
-
- +ds --device-serial [n]umber: string
- device serial number
-
- +sv --software-versions [v]ersions: string
- software versions
-
-3d model measurement units:
-
- +mu --measurement-units [CSD] [CV] [CM]: string
- measurement units with coding scheme designator CSD,
- code value CV and code meaning CM (default: UCUM, um, um)
-.fi
-.PP
-.SS "processing options"
-.PP
-.nf
-other processing options:
-
- -k --key [k]ey: gggg,eeee="str", path or dictionary name="str"
- add further attribute
-.fi
-.PP
-.SS "output options"
-.PP
-.nf
-output file format:
-
- +F --write-file
- write file format (default)
-
- -F --write-dataset
- write data set without file meta information
-
-group length encoding:
-
- +g= --group-length-recalc
- recalculate group lengths if present (default)
-
- +g --group-length-create
- always write with group length elements
-
- -g --group-length-remove
- always write without group length elements
-
-length encoding in sequences and items:
-
- +e --length-explicit
- write with explicit lengths (default)
-
- -e --length-undefined
- write with undefined lengths
-
-data set trailing padding (not with --write-dataset):
-
- -p --padding-off
- no padding (implicit if --write-dataset)
-
- +p --padding-create [f]ile-pad [i]tem-pad: integer
- align file on multiple of f bytes
- and items on multiple of i bytes
-.fi
-.PP
-.SH "NOTES"
-.PP
-.SS "Attribute Sources"
-The application may be fed with some additional input for filling mandatory (and optional) attributes in the new DICOM file like patient, study and series information:
-.PP
-.IP "\(bu" 2
-The \fI--key\fP option can be used to add further attributes to the DICOM output file\&.
-.IP "\(bu" 2
-It is also possible to specify sequences, items and nested attributes using the \fI--key\fP option\&. In these cases, a special 'path' notation has to be used\&. Details on this path notation can be found in the documentation of \fBdcmodify\fP\&.
-.IP "\(bu" 2
-The \fI--key\fP option can be present more than once\&.
-.IP "\(bu" 2
-The value part (after the '=') may be absent causing the attribute to be set with zero length\&.
-.IP "\(bu" 2
-Please be advised that the \fI--key\fP option is applied at the very end, just before saving the DICOM file, so there is no value checking whatsoever\&.
-.PP
-.SH "LOGGING"
-.PP
-The level of logging output of the various command line tools and underlying libraries can be specified by the user\&. By default, only errors and warnings are written to the standard error stream\&. Using option \fI--verbose\fP also informational messages like processing details are reported\&. Option \fI--debug\fP can be used to get more details on the internal activity, e\&.g\&. for debugging purposes\&. Other logging levels can be selected using option \fI--log-level\fP\&. In \fI--quiet\fP mode only fatal errors are reported\&. In such very severe error events, the application will usually terminate\&. For more details on the different logging levels, see documentation of module 'oflog'\&.
-.PP
-In case the logging output should be written to file (optionally with logfile rotation), to syslog (Unix) or the event log (Windows) option \fI--log-config\fP can be used\&. This configuration file also allows for directing only certain messages to a particular output stream and for filtering certain messages based on the module or application where they are generated\&. An example configuration file is provided in \fI<etcdir>/logger\&.cfg\fP\&.
-.SH "COMMAND LINE"
-.PP
-All command line tools use the following notation for parameters: square brackets enclose optional values (0-1), three trailing dots indicate that multiple values are allowed (1-n), a combination of both means 0 to n values\&.
-.PP
-Command line options are distinguished from parameters by a leading '+' or '-' sign, respectively\&. Usually, order and position of command line options are arbitrary (i\&.e\&. they can appear anywhere)\&. However, if options are mutually exclusive the rightmost appearance is used\&. This behavior conforms to the standard evaluation rules of common Unix shells\&.
-.PP
-In addition, one or more command files can be specified using an '@' sign as a prefix to the filename (e\&.g\&. \fI@command\&.txt\fP)\&. Such a command argument is replaced by the content of the corresponding text file (multiple whitespaces are treated as a single separator unless they appear between two quotation marks) prior to any further evaluation\&. Please note that a command file cannot contain another command file\&. This simple but effective approach allows one to summarize common combinations of options/parameters and avoids longish and confusing command lines (an example is provided in file \fI<datadir>/dumppat\&.txt\fP)\&.
-.SH "EXIT CODES"
-.PP
-The \fBstl2dcm\fP utility uses the following exit codes when terminating\&. This enables the user to check for the reason why the application terminated\&.
-.SS "general"
-.PP
-.nf
-EXITCODE_NO_ERROR 0
-EXITCODE_COMMANDLINE_SYNTAX_ERROR 1
-EXITCODE_MEMORY_EXHAUSTED 4
-.fi
-.PP
-.SS "input file errors"
-.PP
-.nf
-EXITCODE_CANNOT_READ_INPUT_FILE 20
-EXITCODE_NO_INPUT_FILES 21
-EXITCODE_INVALID_INPUT_FILE 22
-.fi
-.PP
-.SS "output file errors"
-.PP
-.nf
-EXITCODE_CANNOT_WRITE_OUTPUT_FILE 40
-.fi
-.PP
-.SH "ENVIRONMENT"
-.PP
-The \fBstl2dcm\fP utility will attempt to load DICOM data dictionaries specified in the \fIDCMDICTPATH\fP environment variable\&. By default, i\&.e\&. if the \fIDCMDICTPATH\fP environment variable is not set, the file \fI<datadir>/dicom\&.dic\fP will be loaded unless the dictionary is built into the application (default for Windows)\&.
-.PP
-The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
+\fBdcmencap\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2018-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2018-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "storescp" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "storescp" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
storescp \- DICOM storage (C-STORE) SCP
--fork
fork child process for each association
+
+ --max-associations [m]ax: integer (default: unlimited)
+ limit number of parallel associations to m
.fi
.PP
.SS "network options"
.PP
.nf
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
association negotiation profile from configuration file:
-xf --config-file [f]ilename [p]rofile: string
ElectrooculogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.3
SleepElectroencephalogramWaveformStorage 1.2.840.10008.5.1.4.1.1.9.7.4
BodyPositionWaveformStorage 1.2.840.10008.5.1.4.1.1.9.8.1
+WaveformPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.1
+WaveformAcquisitionPresentationStateStorage 1.2.840.10008.5.1.4.1.1.9.100.2
RETIRED_StandaloneModalityLUTStorage 1.2.840.10008.5.1.4.1.1.10
RETIRED_StandaloneVOILUTStorage 1.2.840.10008.5.1.4.1.1.11
GrayscaleSoftcopyPresentationStateStorage 1.2.840.10008.5.1.4.1.1.11.1
DICONDE_EddyCurrentMultiframeImageStorage 1.2.840.10008.5.1.4.1.1.601.2
DICONDE_ThermographyImageStorage 1.2.840.10008.5.1.4.1.1.601.3
DICONDE_ThermographyMultiFrameImageStorage 1.2.840.10008.5.1.4.1.1.601.4
+DICONDE_UltrasoundWaveformStorage 1.2.840.10008.5.1.4.1.1.601.5
DRAFT_RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.1
RTBeamsDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.7
RTBrachyApplicationSetupDeliveryInstructionStorage 1.2.840.10008.5.1.4.34.10
HighThroughputJPEG2000RPCLImageCompressionLoss.Tr.S. 1.2.840.10008.1.2.4.202
HighThroughputJPEG2000ImageCompressionTransferSynta. 1.2.840.10008.1.2.4.203
RLELosslessTransferSyntax 1.2.840.10008.1.2.5
+DeflatedImageFrameCompressionTransferSyntax 1.2.840.10008.1.2.8.1
.fi
.PP
.PP
\fBstorescu\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1996-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1996-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "storescu" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "storescu" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
storescu \- DICOM storage (C-STORE) SCU
\fBstorescp\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 1996-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1996-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "termscu" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "termscu" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
termscu \- DICOM termination SCU
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 2005-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2005-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "wlmscpfs" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "wlmscpfs" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
wlmscpfs \- DICOM Basic Worklist Management SCP (based on data files)
.SS "network options"
.PP
.nf
+IP protocol version:
+
+ -i4 --ipv4
+ use IPv4 only (default)
+
+ -i6 --ipv6
+ use IPv6 only
+
+ -i0 --ip-auto
+ use IPv6/IPv4 dual stack
+
preferred network transfer syntaxes:
+x= --prefer-uncompr
(0010,1080) MilitaryRank
(0010,2000) MedicalAlerts
(0010,2110) ContrastAllergies
-(0010,2160) EthnicGroup
+(0010,2160) EthnicGroup (retired)
(0010,21a0) SmokingStatus
(0010,21b0) AdditionalPatientHistory
(0010,21c0) PregnancyStatus
The default behavior should be preferred and the \fIDCMDICTPATH\fP environment variable only used when alternative data dictionaries are required\&. The \fIDCMDICTPATH\fP environment variable has the same format as the Unix shell \fIPATH\fP variable in that a colon (':') separates entries\&. On Windows systems, a semicolon (';') is used as a separator\&. The data dictionary code will attempt to load each file specified in the \fIDCMDICTPATH\fP environment variable\&. It is an error if no data dictionary can be loaded\&.
.SH "COPYRIGHT"
.PP
-Copyright (C) 1996-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 1996-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "xml2dcm" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "xml2dcm" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
xml2dcm \- Convert XML document to DICOM file or data set
\fBdcm2xml\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2003-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2003-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
-.TH "xml2dsr" 1 "Wed Dec 11 2024" "Version 3.6.9" "OFFIS DCMTK" \" -*- nroff -*-
+.TH "xml2dsr" 1 "Mon Dec 15 2025" "Version 3.7.0" "OFFIS DCMTK" \" -*- nroff -*-
.nh
.SH NAME
xml2dsr \- Convert XML document to DICOM SR file
PlannedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.74
PerformedImagingAgentAdministrationSRStorage 1.2.840.10008.5.1.4.1.1.88.75
WaveformAnnotationSRStorage 1.2.840.10008.5.1.4.1.1.88.77
+
+RenditionSelectionDocumentRealTimeCommunication 1.2.840.10008.10.4 (*)
.fi
.PP
.PP
+(*) This is not a Storage SOP Class, but used for Real-Time Communication\&.
+.PP
Please note that currently only mandatory and some optional attributes are supported\&.
.SS "Character Encoding"
The DICOM character encoding is determined automatically from the element with tag '0008,0005' (Specific Character Set) - if present\&. The following character sets are currently supported (requires \fBlibxml\fP to include \fBiconv\fP support, see \fI--version\fP output):
\fBdsr2xml\fP(1)
.SH "COPYRIGHT"
.PP
-Copyright (C) 2003-2024 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
+Copyright (C) 2003-2025 by OFFIS e\&.V\&., Escherweg 2, 26121 Oldenburg, Germany\&.
*/
#include "dcmtk/config/osconfig.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#include <assert.h>
#include <errno.h>
#include <limits.h>
if (rowcol_len <= 32 / rowcol_bits)
break;
/*FALLTHROUGH*/
- default:
+ default:
goto bad;
}
rowcol_mask = 1u << (rowcol_bits - 1);
-/* A Bison parser, made by GNU Bison 3.7.5. */
+/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison implementation for Yacc-like parsers in C
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
USER NAME SPACE" below. */
/* Identify Bison output, and Bison version. */
-#define YYBISON 30705
+#define YYBISON 30802
/* Bison version string. */
-#define YYBISON_VERSION "3.7.5"
+#define YYBISON_VERSION "3.8.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
*/
#include "dcmtk/config/osconfig.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#include <assert.h>
#include <errno.h>
#include <limits.h>
static void set_range(uint32_t, uint32_t);
static void set_src(linear_zone_t *, uint32_t, uint32_t);
-#line 307 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 305 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
# ifndef YY_CAST
# ifdef __cplusplus
# define YY_USE(E) /* empty */
#endif
-#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
+# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
+# else
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# endif
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
};
#if YYDEBUG
- /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_int16 yyrline[] =
{
- 0, 256, 256, 259, 260, 261, 262, 263, 264, 265,
- 266, 267, 269, 270, 271, 272, 274, 275, 277, 278,
- 281, 285, 286, 287, 288, 290, 291, 293, 294, 296,
- 297, 299, 301, 303, 307, 311, 317, 320, 324, 328,
- 332, 333
+ 0, 254, 254, 257, 258, 259, 260, 261, 262, 263,
+ 264, 265, 267, 268, 269, 270, 272, 273, 275, 276,
+ 279, 283, 284, 285, 286, 288, 289, 291, 292, 294,
+ 295, 297, 299, 301, 305, 309, 315, 318, 322, 326,
+ 330, 331
};
#endif
}
#endif
-#ifdef YYPRINT
-/* YYTOKNUM[NUM] -- (External) token number corresponding to the
- (internal) symbol number NUM (which must be that of a token). */
-static const yytype_int16 yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 269, 270, 271, 272, 45, 47,
- 61
-};
-#endif
-
#define YYPACT_NINF (-39)
#define yypact_value_is_default(Yyn) \
#define yytable_value_is_error(Yyn) \
0
- /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
static const yytype_int8 yypact[] =
{
-39, 12, -1, -39, 3, 4, 7, 9, 10, 11,
14, 25, -39
};
- /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE does not specify something else to do. Zero
- means the default is an error. */
+/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
static const yytype_int8 yydefact[] =
{
3, 0, 0, 1, 0, 0, 0, 0, 0, 0,
20, 0, 17
};
- /* YYPGOTO[NTERM-NUM]. */
+/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
-39, -39, -39, -39, -39, -39, -38, -39, -39, -39,
-39, -20
};
- /* YYDEFGOTO[NTERM-NUM]. */
+/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
0, 1, 2, 13, 14, 23, 26, 58, 15, 27,
45, 32
};
- /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule whose
- number is the opposite. If YYTABLE_NINF, syntax error. */
+/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int8 yytable[] =
{
36, 47, 4, 5, 6, 7, 8, 9, 10, 33,
20, 19, 18, -1, 19
};
- /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
+/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
+ state STATE-NUM. */
static const yytype_int8 yystos[] =
{
0, 22, 23, 0, 3, 4, 5, 6, 7, 8,
16, 27, 19
};
- /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
static const yytype_int8 yyr1[] =
{
0, 21, 22, 23, 23, 23, 23, 23, 23, 23,
42, 42
};
- /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
static const yytype_int8 yyr2[] =
{
0, 2, 3, 0, 2, 2, 2, 2, 2, 2,
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
#define YYERROR goto yyerrorlab
+#define YYNOMEM goto yyexhaustedlab
#define YYRECOVERING() (!!yyerrstatus)
YYFPRINTF Args; \
} while (0)
-/* This macro is provided for backward compatibility. */
-# ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
+
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
YY_USE (yyoutput);
if (!yyvaluep)
return;
-# ifdef YYPRINT
- if (yykind < YYNTOKENS)
- YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
-# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
YYDPRINTF ((stderr, "Starting parse\n"));
yychar = YYEMPTY; /* Cause a token to be read. */
+
goto yysetstate;
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
- goto yyexhaustedlab;
+ YYNOMEM;
#else
{
/* Get the current used size of the three stacks, in elements. */
# else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
+ YYNOMEM;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
YY_CAST (union yyalloc *,
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr)
- goto yyexhaustedlab;
+ YYNOMEM;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
}
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
+
if (yystate == YYFINAL)
YYACCEPT;
switch (yyn)
{
case 2: /* file: property mapping lns */
-#line 257 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 255 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ dump_file(); }
-#line 1381 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1370 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 12: /* name: R_NAME L_STRING */
-#line 269 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 267 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_name((yyvsp[0].s_value)); (yyvsp[0].s_value) = NULL; }
-#line 1387 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1376 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 13: /* type: R_TYPE types */
-#line 270 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 268 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_type((yyvsp[0].i_value)); }
-#line 1393 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1382 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 14: /* types: R_ROWCOL */
-#line 271 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 269 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ (yyval.i_value) = R_ROWCOL; }
-#line 1399 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1388 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 15: /* range: L_IMM '-' L_IMM */
-#line 272 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 270 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_range((yyvsp[-2].i_value), (yyvsp[0].i_value)); }
-#line 1405 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1394 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 18: /* src_zone: R_SRC_ZONE zone */
-#line 277 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 275 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_src_zone((yyvsp[0].i_value)); }
-#line 1411 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1400 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 19: /* zone: range */
-#line 278 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 276 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
(yyval.i_value) = 32;
}
-#line 1419 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1408 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 20: /* zone: range '/' range '/' ranges L_IMM */
-#line 281 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 279 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
(yyval.i_value) = (yyvsp[0].i_value);
}
-#line 1427 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1416 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 21: /* dst_invalid: R_DST_INVALID L_IMM */
-#line 285 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 283 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_dst_invalid((yyvsp[0].i_value)); }
-#line 1433 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1422 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 22: /* dst_ilseq: R_DST_ILSEQ L_IMM */
-#line 286 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 284 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_dst_ilseq((yyvsp[0].i_value)); }
-#line 1439 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1428 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 23: /* dst_unit_bits: R_DST_UNIT_BITS L_IMM */
-#line 287 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 285 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_dst_unit_bits((yyvsp[0].i_value)); }
-#line 1445 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1434 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 24: /* oob_mode: R_OOB_MODE oob_mode_sel */
-#line 288 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 286 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ set_oob_mode((yyvsp[0].i_value)); }
-#line 1451 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1440 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 25: /* oob_mode_sel: R_INVALID */
-#line 290 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 288 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ (yyval.i_value) = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL; }
-#line 1457 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1446 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 26: /* oob_mode_sel: R_ILSEQ */
-#line 291 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 289 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ (yyval.i_value) = _CITRUS_MAPPER_STD_OOB_ILSEQ; }
-#line 1463 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1452 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 28: /* begin_map: R_BEGIN_MAP lns */
-#line 294 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 292 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ setup_map(); }
-#line 1469 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1458 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 31: /* map_elem: src '=' dst */
-#line 300 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 298 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ store(&(yyvsp[-2].lz_value), (yyvsp[0].i_value), 0); }
-#line 1475 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1464 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 32: /* map_elem: src '=' L_IMM '-' */
-#line 302 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 300 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{ store(&(yyvsp[-3].lz_value), (yyvsp[-1].i_value), 1); }
-#line 1481 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1470 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 33: /* dst: L_IMM */
-#line 304 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 302 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
(yyval.i_value) = (yyvsp[0].i_value);
}
-#line 1489 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1478 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 34: /* dst: R_INVALID */
-#line 308 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 306 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
(yyval.i_value) = dst_invalid;
}
-#line 1497 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1486 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 35: /* dst: R_ILSEQ */
-#line 312 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 310 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
(yyval.i_value) = dst_ilseq;
}
-#line 1505 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1494 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 36: /* src: %empty */
-#line 317 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 315 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
set_src(&(yyval.lz_value), src_next, src_next);
}
-#line 1513 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1502 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 37: /* src: L_IMM */
-#line 321 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 319 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
set_src(&(yyval.lz_value), (yyvsp[0].i_value), (yyvsp[0].i_value));
}
-#line 1521 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1510 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 38: /* src: L_IMM '-' L_IMM */
-#line 325 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 323 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
set_src(&(yyval.lz_value), (yyvsp[-2].i_value), (yyvsp[0].i_value));
}
-#line 1529 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1518 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
case 39: /* src: '-' L_IMM */
-#line 329 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 327 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
{
set_src(&(yyval.lz_value), src_next, (yyvsp[0].i_value));
}
-#line 1537 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1526 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
break;
-#line 1541 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
+#line 1530 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper_bison.cc"
default: break;
}
label yyerrorlab therefore never appears in user code. */
if (0)
YYERROR;
+ ++yynerrs;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
`-------------------------------------*/
yyacceptlab:
yyresult = 0;
- goto yyreturn;
+ goto yyreturnlab;
/*-----------------------------------.
`-----------------------------------*/
yyabortlab:
yyresult = 1;
- goto yyreturn;
+ goto yyreturnlab;
-#if !defined yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
+/*-----------------------------------------------------------.
+| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
+`-----------------------------------------------------------*/
yyexhaustedlab:
yyerror (YY_("memory exhausted"));
yyresult = 2;
- goto yyreturn;
-#endif
+ goto yyreturnlab;
-/*-------------------------------------------------------.
-| yyreturn -- parsing is finished, clean up and return. |
-`-------------------------------------------------------*/
-yyreturn:
+/*----------------------------------------------------------.
+| yyreturnlab -- parsing is finished, clean up and return. |
+`----------------------------------------------------------*/
+yyreturnlab:
if (yychar != YYEMPTY)
{
/* Make sure we have latest lookahead translation. See comments at
return yyresult;
}
-#line 335 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 333 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
static void
if (rowcol_len <= 32 / rowcol_bits)
break;
/*FALLTHROUGH*/
- default:
+ default:
goto bad;
}
rowcol_mask = 1u << (rowcol_bits - 1);
-/* A Bison parser, made by GNU Bison 3.7.5. */
+/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison interface for Yacc-like parsers in C
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
-#line 237 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
+#line 235 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkcsmapper.y"
uint32_t i_value;
char *s_value;
extern YYSTYPE yylval;
+
int yyparse (void);
+
#endif /* !YY_YY_HOME_MEICHEL_DICOM_DCMTK_FULL_PUBLIC_OFICONV_APPS_MKCSMAPPER_BISON_H_INCLUDED */
*/
#include "dcmtk/config/osconfig.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#else
-/* A Bison parser, made by GNU Bison 3.7.5. */
+/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison implementation for Yacc-like parsers in C
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
USER NAME SPACE" below. */
/* Identify Bison output, and Bison version. */
-#define YYBISON 30705
+#define YYBISON 30802
/* Bison version string. */
-#define YYBISON_VERSION "3.7.5"
+#define YYBISON_VERSION "3.8.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
*/
#include "dcmtk/config/osconfig.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#else
static void set_invalid(uint32_t);
static void set_prop_string(const char *, char **, char **);
-#line 279 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 277 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
# ifndef YY_CAST
# ifdef __cplusplus
# define YY_USE(E) /* empty */
#endif
-#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized. */
-# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__
+# if __GNUC__ * 100 + __GNUC_MINOR__ < 407
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")
+# else
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \
_Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# endif
# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
_Pragma ("GCC diagnostic pop")
#else
};
#if YYDEBUG
- /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
+/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 220, 220, 223, 224, 225, 226, 227, 228, 229,
- 231, 236, 240, 244, 249
+ 0, 218, 218, 221, 222, 223, 224, 225, 226, 227,
+ 229, 234, 238, 242, 247
};
#endif
}
#endif
-#ifdef YYPRINT
-/* YYTOKNUM[NUM] -- (External) token number corresponding to the
- (internal) symbol number NUM (which must be that of a token). */
-static const yytype_int16 yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265
-};
-#endif
-
#define YYPACT_NINF (-4)
#define yypact_value_is_default(Yyn) \
#define yytable_value_is_error(Yyn) \
0
- /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
static const yytype_int8 yypact[] =
{
-4, 6, -3, -4, -2, -1, 0, 1, 3, -4,
-4, -4, -4, -4, -4, -4
};
- /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE does not specify something else to do. Zero
- means the default is an error. */
+/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
static const yytype_int8 yydefact[] =
{
3, 0, 2, 1, 0, 0, 0, 0, 0, 4,
5, 6, 7, 8, 9, 13
};
- /* YYPGOTO[NTERM-NUM]. */
+/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
-4, -4, -4, -4, -4, -4, -4, -4
};
- /* YYDEFGOTO[NTERM-NUM]. */
+/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
0, 1, 2, 10, 11, 12, 13, 14
};
- /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule whose
- number is the opposite. If YYTABLE_NINF, syntax error. */
+/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_int8 yytable[] =
{
4, 5, 6, 7, 8, 9, 3, 0, 15, 16,
9
};
- /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
+/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of
+ state STATE-NUM. */
static const yytype_int8 yystos[] =
{
0, 12, 13, 0, 3, 4, 5, 6, 7, 8,
8, 8, 8, 8, 8, 9
};
- /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */
static const yytype_int8 yyr1[] =
{
0, 11, 12, 13, 13, 13, 13, 13, 13, 13,
14, 15, 16, 17, 18
};
- /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */
static const yytype_int8 yyr2[] =
{
0, 2, 1, 0, 2, 3, 3, 3, 3, 3,
#define YYACCEPT goto yyacceptlab
#define YYABORT goto yyabortlab
#define YYERROR goto yyerrorlab
+#define YYNOMEM goto yyexhaustedlab
#define YYRECOVERING() (!!yyerrstatus)
YYFPRINTF Args; \
} while (0)
-/* This macro is provided for backward compatibility. */
-# ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
+
# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \
YY_USE (yyoutput);
if (!yyvaluep)
return;
-# ifdef YYPRINT
- if (yykind < YYNTOKENS)
- YYPRINT (yyo, yytoknum[yykind], *yyvaluep);
-# endif
YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
YY_USE (yykind);
YY_IGNORE_MAYBE_UNINITIALIZED_END
YYDPRINTF ((stderr, "Starting parse\n"));
yychar = YYEMPTY; /* Cause a token to be read. */
+
goto yysetstate;
if (yyss + yystacksize - 1 <= yyssp)
#if !defined yyoverflow && !defined YYSTACK_RELOCATE
- goto yyexhaustedlab;
+ YYNOMEM;
#else
{
/* Get the current used size of the three stacks, in elements. */
# else /* defined YYSTACK_RELOCATE */
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
+ YYNOMEM;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
yystacksize = YYMAXDEPTH;
YY_CAST (union yyalloc *,
YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
if (! yyptr)
- goto yyexhaustedlab;
+ YYNOMEM;
YYSTACK_RELOCATE (yyss_alloc, yyss);
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
}
#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */
+
if (yystate == YYFINAL)
YYACCEPT;
switch (yyn)
{
case 2: /* file: property */
-#line 221 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 219 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
{ dump_file(); }
-#line 1294 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 1284 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
break;
case 10: /* name: R_NAME L_STRING */
-#line 232 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 230 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
{
set_prop_string("NAME", &name, &(yyvsp[0].s_value));
}
-#line 1302 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 1292 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
break;
case 11: /* encoding: R_ENCODING L_STRING */
-#line 237 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 235 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
{
set_prop_string("ENCODING", &encoding, &(yyvsp[0].s_value));
}
-#line 1310 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 1300 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
break;
case 12: /* variable: R_VARIABLE L_STRING */
-#line 241 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 239 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
{
set_prop_string("VARIABLE", &variable, &(yyvsp[0].s_value));
}
-#line 1318 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 1308 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
break;
case 13: /* defcsid: R_DEFCSID L_STRING L_IMM */
-#line 245 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 243 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
{
register_named_csid((yyvsp[-1].s_value), (yyvsp[0].i_value));
(yyvsp[-1].s_value) = NULL;
}
-#line 1327 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 1317 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
break;
case 14: /* invalid: R_INVALID L_IMM */
-#line 250 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 248 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
{
set_invalid((yyvsp[0].i_value));
}
-#line 1335 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 1325 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
break;
-#line 1339 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
+#line 1329 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb_bison.cc"
default: break;
}
label yyerrorlab therefore never appears in user code. */
if (0)
YYERROR;
+ ++yynerrs;
/* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
`-------------------------------------*/
yyacceptlab:
yyresult = 0;
- goto yyreturn;
+ goto yyreturnlab;
/*-----------------------------------.
`-----------------------------------*/
yyabortlab:
yyresult = 1;
- goto yyreturn;
+ goto yyreturnlab;
-#if !defined yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
+/*-----------------------------------------------------------.
+| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. |
+`-----------------------------------------------------------*/
yyexhaustedlab:
yyerror (YY_("memory exhausted"));
yyresult = 2;
- goto yyreturn;
-#endif
+ goto yyreturnlab;
-/*-------------------------------------------------------.
-| yyreturn -- parsing is finished, clean up and return. |
-`-------------------------------------------------------*/
-yyreturn:
+/*----------------------------------------------------------.
+| yyreturnlab -- parsing is finished, clean up and return. |
+`----------------------------------------------------------*/
+yyreturnlab:
if (yychar != YYEMPTY)
{
/* Make sure we have latest lookahead translation. See comments at
return yyresult;
}
-#line 253 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 251 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
int
-/* A Bison parser, made by GNU Bison 3.7.5. */
+/* A Bison parser, made by GNU Bison 3.8.2. */
/* Bison interface for Yacc-like parsers in C
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE
{
-#line 208 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
+#line 206 "/home/meichel/dicom/dcmtk-full/public/oficonv/apps/mkesdb.y"
uint32_t i_value;
char *s_value;
extern YYSTYPE yylval;
+
int yyparse (void);
+
#endif /* !YY_YY_HOME_MEICHEL_DICOM_DCMTK_FULL_PUBLIC_OFICONV_APPS_MKESDB_BISON_H_INCLUDED */
// perform the conversion
size_t result = OFiconv(id, &src_ptr, &src_len, &dst_ptr, &dst_len);
+
+ // null terminate
+ if (dst_len > 0) *dst_ptr = '\0';
+
if (result != OFstatic_cast(size_t, -1))
{
std::cout << "UTF-8 string: " << output << std::endl;
#include "dcmtk/config/osconfig.h"
#include "dcmtk/oficonv/oidefine.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#include <wchar.h>
#include <stdint.h>
/** resolve the character encoding name specified by the name argument
* to its canonical form.
+ * The resolved name is returned in a newly allocated buffer that must be freed by the caller using free().
* @param name encoding name
* @return canonical encoding name, NULL if unknown
*/
-DCMTK_OFICONV_EXPORT const char *OFiconv_canonicalize(const char *name);
+DCMTK_OFICONV_EXPORT char *OFiconv_canonicalize(const char *name);
/** This function can retrieve or set specific conversion setting from the
* cd conversion descriptor. The request parameter specifies the operation
*/
DCMTK_OFICONV_EXPORT int OFiconvctl(iconv_t cd, int request, void *argument);
+/** This function define a runtime path where to look for the oficonv db files.
+ * This path is used only after the env variable DCMICONVPATH.
+ * @param path to the location of esdb folder
+ */
+DCMTK_OFICONV_EXPORT void OFiconv_setpath(const char *iconv_path);
+
/// space holder type for OFlocale_charset().
typedef struct {
char spaceholder[20];
citrus_bcs.o: citrus_bcs.c ../../config/include/dcmtk/config/osconfig.h \
- citrus_bcs.h
+ ../include/dcmtk/oficonv/iconv.h ../include/dcmtk/oficonv/oidefine.h \
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h citrus_bcs.h
citrus_bcs_strtol.o: citrus_bcs_strtol.c \
../../config/include/dcmtk/config/osconfig.h citrus_bcs.h \
citrus_strtol.h
oficonv_logger.o: oficonv_logger.c \
../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/oficonv/iconv.h ../include/dcmtk/oficonv/oidefine.h \
- ../../ofstd/include/dcmtk/ofstd/ofexport.h
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h citrus_lock.h
oficonv_strcasestr.o: oficonv_strcasestr.c \
../../config/include/dcmtk/config/osconfig.h oficonv_strcasestr.h
oficonv_strlcpy.o: oficonv_strlcpy.c \
*/
#include "dcmtk/config/osconfig.h"
+#include "dcmtk/oficonv/iconv.h"
#include "citrus_bcs.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+char *oficonv_path = NULL;
+
+void OFiconv_setpath(const char *runtime_path) {
+ if (oficonv_path) {
+ free(oficonv_path);
+ oficonv_path = NULL;
+ }
+ if (runtime_path) {
+ oficonv_path = strdup(runtime_path);
+ }
+}
+
/*
* case insensitive comparison between two C strings.
*/
// retrieve the DCMICONVPATH environment variable
env = getenv(OFICONV_PATH_VARIABLE);
+ // if the environment variable is not set, use the runtime oficonv path instead:
+ if ( env == NULL && oficonv_path != NULL ) env = oficonv_path;
+
// if the environment variable is not set, use DEFAULT_SUPPORT_DATA_DIR instead
if (env == NULL) env = DEFAULT_SUPPORT_DATA_DIR;
#include "dcmtk/config/osconfig.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#include "dcmtk/oficonv/queue.h"
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include "citrus_csmapper.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#else
#include "dcmtk/config/osconfig.h"
#include "citrus_db.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_db_factory.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#else
#include "dcmtk/config/osconfig.h"
#include "citrus_db_hash.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <stdio.h>
#include <string.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_dechanyu.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
#ifndef __CONCAT
#define __CONCAT(x,y) x ## y
#endif
#include "dcmtk/config/osconfig.h"
#include "citrus_esdb.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_euc.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_euctw.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_gbk2k.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_hash.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <stdio.h>
#include <string.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_hz.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#else
#include "dcmtk/config/osconfig.h"
#include "citrus_iconv.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_QUEUE_H
#include <sys/queue.h>
#else
int ret;
#ifdef DCMTK_ENABLE_ICONV_PASSTHROUGH
- /*
+ /*
* Use a pass-through when the (src,dest) encodings are the same.
*/
module = (strcmp(src, dst) != 0) ? "iconv_std" : "iconv_none";
}
}
-const char
+char
*_citrus_iconv_canonicalize(const char *name)
{
char *buf;
struct _citrus_iconv;
BEGIN_EXTERN_C
-int _citrus_iconv_open(struct _citrus_iconv * * ,
- const char * , const char * );
-void _citrus_iconv_close(struct _citrus_iconv *);
-void _citrus_iconv_close_nofree(struct _citrus_iconv *);
-const char *_citrus_iconv_canonicalize(const char *);
+int _citrus_iconv_open(struct _citrus_iconv * * , const char * , const char * );
+void _citrus_iconv_close(struct _citrus_iconv *);
+void _citrus_iconv_close_nofree(struct _citrus_iconv *);
+char *_citrus_iconv_canonicalize(const char *);
END_EXTERN_C
_citrus_module_t ci_module;
unsigned int ci_used_count;
char *ci_convname;
- bool ci_discard_ilseq;
- struct iconv_hooks *ci_hooks;
- bool ci_ilseq_invalid;
};
struct _citrus_iconv {
struct _citrus_iconv_shared *cv_shared;
void *cv_closure;
+ struct iconv_hooks *ci_hooks;
+ bool ci_discard_ilseq;
+ bool ci_ilseq_invalid;
};
#endif
len = *outbytes;
}
memcpy(*out, *in, len);
- in += len;
+ *in += len;
*inbytes -= len;
- out += len;
+ *out += len;
*outbytes -= len;
*invalids = 0;
if (e2big)
tmpin = *in;
szrin = szrout = 0;
ret = mbtocsx(&sc->sc_src_encoding, &csid, &idx, &tmpin,
- *inbytes, &szrin, cv->cv_shared->ci_hooks);
+ *inbytes, &szrin, cv->ci_hooks);
if (ret != 0 && (ret != EILSEQ ||
- !cv->cv_shared->ci_discard_ilseq)) {
+ !cv->ci_discard_ilseq)) {
goto err;
} else if (ret == EILSEQ) {
/*
* Some software depends on this behavior
* though this is against POSIX specification.
*/
- if (cv->cv_shared->ci_ilseq_invalid != 0) {
+ if (cv->ci_ilseq_invalid != 0) {
ret = EILSEQ;
goto err;
}
inval++;
szrout = 0;
if ((((flags & _CITRUS_ICONV_F_HIDE_INVALID) == 0) &&
- !cv->cv_shared->ci_discard_ilseq) &&
+ !cv->ci_discard_ilseq) &&
is->is_use_invalid) {
ret = wctombx(&sc->sc_dst_encoding,
*out, *outbytes, is->is_invalid,
- &szrout, cv->cv_shared->ci_hooks);
+ &szrout, cv->ci_hooks);
if (ret)
goto err;
}
/* csid/index -> mb */
ret = cstombx(&sc->sc_dst_encoding,
*out, *outbytes, csid, idx, &szrout,
- cv->cv_shared->ci_hooks);
+ cv->ci_hooks);
if (ret)
goto err;
next:
#include "dcmtk/config/osconfig.h"
#include "citrus_iso2022.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_euc.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_johab.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#ifdef HAVE_WINDOWS_H
#include <windows.h>
-#define WLOCK(lock) AcquireSRWLockExclusive(lock);
-#define UNLOCK(lock) ReleaseSRWLockExclusive(lock);
+#define WLOCK(lock) AcquireSRWLockExclusive(lock);
+#define UNLOCK(lock) ReleaseSRWLockExclusive(lock);
+#define RLOCK(lock) AcquireSRWLockShared(lock);
+#define UNRLOCK(lock) ReleaseSRWLockShared(lock);
#else /* HAVE_WINDOWS_H */
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
-#define WLOCK(lock) pthread_rwlock_wrlock(lock);
-#define UNLOCK(lock) pthread_rwlock_unlock(lock);
+#define WLOCK(lock) pthread_rwlock_wrlock(lock);
+#define UNLOCK(lock) pthread_rwlock_unlock(lock);
+#define RLOCK(lock) pthread_rwlock_rdlock(lock);
+#define UNRLOCK(lock) pthread_rwlock_unlock(lock);
#else /* HAVE_PTHREAD_H */
#else /* WITH_THREADS */
-#define WLOCK(lock) /* nothing */ ;
-#define UNLOCK(lock) /* nothing */ ;
+#define WLOCK(lock) /* nothing */ ;
+#define UNLOCK(lock) /* nothing */ ;
+#define RLOCK(lock) /* nothing */ ;
+#define UNRLOCK(lock) /* nothing */ ;
#endif /* WITH_THREADS */
#include "dcmtk/config/osconfig.h"
#include "citrus_lookup.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#include "dcmtk/config/osconfig.h"
#include "citrus_mapper.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
#ifdef HAVE_SYS_QUEUE_H
#include <sys/queue.h>
/* get module name */
*module = p;
cq = _citrus_bcs_skip_nonws_len(cp, &len);
- strlcpy(p, cp, (size_t)(cq - cp + 1));
+ /* we cannot use strlcpy here because cp is not guaranteed to be null terminated */
+ strncpy(p, cp, (size_t)(cq - cp));
+ *(p + (cq - cp)) = '\0';
p += cq - cp + 1;
/* get variable */
*variable = p;
cp = _citrus_bcs_skip_ws_len(cq, &len);
- strlcpy(p, cp, len + 1);
-
+ /* we cannot use strlcpy here because cp is not guaranteed to be null terminated */
+ strncpy(p, cp, len);
+ *(p+len) = '\0';
ret = 0;
quit:
/*ARGSUSED*/
_citrus_mapper_zone_mapper_uninit(struct _citrus_csmapper *cm )
{
- (void) cm;
+ if (cm && cm->cm_closure)
+ free(cm->cm_closure);
}
static int
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
#include <errno.h>
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* for O_RDONLY, O_CLOEXEC */
-#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_module.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#include "dcmtk/config/osconfig.h"
#include "citrus_mskanji.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include "dcmtk/oficonv/iconv.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
-
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
struct _citrus_region {
#include "dcmtk/config/osconfig.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#include <stdint.h>
#ifndef OFICONV_CITRUS_WC_T_DEFINED
#include "dcmtk/config/osconfig.h"
#include "citrus_utf1632.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_utf8.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
(var) = (tvar))
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include "dcmtk/config/osconfig.h"
#include "citrus_zw.h"
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
-
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include "dcmtk/oficonv/queue.h"
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
-
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
return ((iconv_t)-1);
}
- handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE");
- handle->cv_shared->ci_ilseq_invalid = false;
- handle->cv_shared->ci_hooks = NULL;
+ handle->ci_discard_ilseq = strcasestr(out, "//IGNORE");
+ handle->ci_ilseq_invalid = false;
+ handle->ci_hooks = NULL;
return ((iconv_t)(void *)handle);
}
OF__iconv_free_list(list, sz);
}
-const char
-*OFiconv_canonicalize(const char *name)
+char *OFiconv_canonicalize(const char *name)
{
-
return (_citrus_iconv_canonicalize(name));
}
case ICONV_SET_TRANSLITERATE:
return ((*i == 1) ? 0 : -1);
case ICONV_GET_DISCARD_ILSEQ:
- *i = cv->cv_shared->ci_discard_ilseq ? 1 : 0;
+ *i = cv->ci_discard_ilseq ? 1 : 0;
return (0);
case ICONV_SET_DISCARD_ILSEQ:
- cv->cv_shared->ci_discard_ilseq = *i;
+ cv->ci_discard_ilseq = *i;
return (0);
case ICONV_SET_HOOKS:
- cv->cv_shared->ci_hooks = hooks;
+ cv->ci_hooks = hooks;
return (0);
case ICONV_SET_FALLBACKS:
errno = EOPNOTSUPP;
return (-1);
case ICONV_GET_ILSEQ_INVALID:
- *i = cv->cv_shared->ci_ilseq_invalid ? 1 : 0;
+ *i = cv->ci_ilseq_invalid ? 1 : 0;
return (0);
case ICONV_SET_ILSEQ_INVALID:
- cv->cv_shared->ci_ilseq_invalid = *i;
+ cv->ci_ilseq_invalid = *i;
return (0);
default:
errno = EINVAL;
void OFiconv_cleanup()
{
_citrus_csmapper_free();
+ OFiconv_setpath(NULL);
}
#include "dcmtk/config/osconfig.h"
#include "dcmtk/oficonv/iconv.h"
+#include "citrus_lock.h"
#include <stdio.h>
+#ifdef WITH_THREADS
+#ifdef HAVE_WINDOWS_H
+static SRWLOCK logger_lock = SRWLOCK_INIT;
+#elif defined(HAVE_PTHREAD_H)
+static pthread_rwlock_t logger_lock = PTHREAD_RWLOCK_INITIALIZER;
+#endif
+#endif
+
static oficonv_logger_callback_t logger_callback = NULL;
static int log_level = 3;
void set_oficonv_logger_callback(oficonv_logger_callback_t callback)
{
+ WLOCK(&logger_lock);
logger_callback = callback;
+ UNLOCK(&logger_lock);
}
oficonv_logger_callback_t get_oficonv_logger_callback()
{
- return logger_callback;
+ RLOCK(&logger_lock);
+ oficonv_logger_callback_t result = logger_callback;
+ UNRLOCK(&logger_lock);
+ return result;
}
void set_oficonv_log_level(int level)
void oficonv_log(int level, const char *text1, const char *text2, const char *text3)
{
+ RLOCK(&logger_lock);
if (logger_callback) logger_callback(level, text1, text2, text3);
else
{
}
if (level >= log_level) fprintf(stderr, "%s %s%s%s\n", level_text, text1, text2, text3);
}
+ UNRLOCK(&logger_lock);
}
/*
*
- * Copyright (C) 2022, OFFIS e.V.
+ * Copyright (C) 2022-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFTEST_REGISTER(oflocale_charset);
OFTEST_REGISTER(oficonvctl);
+// finally clean up memory
+OFTEST_REGISTER(oficonv_cleanup);
+
OFTEST_MAIN("oficonv")
OFTEST(oficonv_canonicalize)
{
- const char *c;
+ char *c;
// these are the canonical names we expect as result
OFString latin1("ISO-8859-1");
// exercise all synonyms for ISO-8859-1 as defined in oficonv/datasrc/esdb/esdb.alias,
// with mixed uppercase/lowercase spellings
- c = OFiconv_canonicalize("cp819"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("csisolatin1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("ibm819"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("iso_8859-1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("iso_8859-1:1987"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("iso-ir-100"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("iso8859-1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("l1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("latin1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("CP819"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("CSISOLATIN1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("IBM819"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("ISO_8859-1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("ISO_8859-1:1987"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("ISO-IR-100"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("ISO8859-1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("L1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("LATIN1"); OFCHECK(c && latin1 == c);
- c = OFiconv_canonicalize("cSiSoLaTiN1"); OFCHECK(c && latin1 == c);
+ c = OFiconv_canonicalize("cp819"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("csisolatin1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("ibm819"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso_8859-1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso_8859-1:1987"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso-ir-100"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso8859-1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("l1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("latin1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("CP819"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("CSISOLATIN1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("IBM819"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("ISO_8859-1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("ISO_8859-1:1987"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("ISO-IR-100"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("ISO8859-1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("L1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("LATIN1"); OFCHECK(c && latin1 == c); if (c) free(c);
+ c = OFiconv_canonicalize("cSiSoLaTiN1"); OFCHECK(c && latin1 == c); if (c) free(c);
// exercise at least one synonym for each supported character set
- c = OFiconv_canonicalize("gb2312"); OFCHECK(c && euc_cn == c);
- c = OFiconv_canonicalize("iso-ir-149"); OFCHECK(c && euc_kr == c);
- c = OFiconv_canonicalize("iso-ir-101"); OFCHECK(c && latin2 == c);
- c = OFiconv_canonicalize("latin3"); OFCHECK(c && latin3 == c);
- c = OFiconv_canonicalize("iso_8859-4"); OFCHECK(c && latin4 == c);
- c = OFiconv_canonicalize("cyrillic"); OFCHECK(c && cyrillic == c);
- c = OFiconv_canonicalize("arabic"); OFCHECK(c && arabic == c);
- c = OFiconv_canonicalize("greek"); OFCHECK(c && greek == c);
- c = OFiconv_canonicalize("hebrew"); OFCHECK(c && hebrew == c);
- c = OFiconv_canonicalize("iso-ir-148"); OFCHECK(c && latin5 == c);
- c = OFiconv_canonicalize("tis-620"); OFCHECK(c && thai == c);
- c = OFiconv_canonicalize("iso-ir-203"); OFCHECK(c && latin9 == c);
- c = OFiconv_canonicalize("ascii"); OFCHECK(c && ascii == c);
- c = OFiconv_canonicalize("jis_x0201"); OFCHECK(c && jisx0201 == c);
- c = OFiconv_canonicalize("jis0208"); OFCHECK(c && jisx0208 == c);
- c = OFiconv_canonicalize("ms_kanji"); OFCHECK(c && shift_jis == c);
- c = OFiconv_canonicalize("jis_x0212"); OFCHECK(c && jisx0212 == c);
- c = OFiconv_canonicalize("utf8"); OFCHECK(c && utf8 == c);
- c = OFiconv_canonicalize("unicode"); OFCHECK(c && utf16 == c);
+ c = OFiconv_canonicalize("gb2312"); OFCHECK(c && euc_cn == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso-ir-149"); OFCHECK(c && euc_kr == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso-ir-101"); OFCHECK(c && latin2 == c); if (c) free(c);
+ c = OFiconv_canonicalize("latin3"); OFCHECK(c && latin3 == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso_8859-4"); OFCHECK(c && latin4 == c); if (c) free(c);
+ c = OFiconv_canonicalize("cyrillic"); OFCHECK(c && cyrillic == c); if (c) free(c);
+ c = OFiconv_canonicalize("arabic"); OFCHECK(c && arabic == c); if (c) free(c);
+ c = OFiconv_canonicalize("greek"); OFCHECK(c && greek == c); if (c) free(c);
+ c = OFiconv_canonicalize("hebrew"); OFCHECK(c && hebrew == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso-ir-148"); OFCHECK(c && latin5 == c); if (c) free(c);
+ c = OFiconv_canonicalize("tis-620"); OFCHECK(c && thai == c); if (c) free(c);
+ c = OFiconv_canonicalize("iso-ir-203"); OFCHECK(c && latin9 == c); if (c) free(c);
+ c = OFiconv_canonicalize("ascii"); OFCHECK(c && ascii == c); if (c) free(c);
+ c = OFiconv_canonicalize("jis_x0201"); OFCHECK(c && jisx0201 == c); if (c) free(c);
+ c = OFiconv_canonicalize("jis0208"); OFCHECK(c && jisx0208 == c); if (c) free(c);
+ c = OFiconv_canonicalize("ms_kanji"); OFCHECK(c && shift_jis == c); if (c) free(c);
+ c = OFiconv_canonicalize("jis_x0212"); OFCHECK(c && jisx0212 == c); if (c) free(c);
+ c = OFiconv_canonicalize("utf8"); OFCHECK(c && utf8 == c); if (c) free(c);
+ c = OFiconv_canonicalize("unicode"); OFCHECK(c && utf16 == c); if (c) free(c);
}
OFiconv_close(id3);
}
}
+
+OFTEST(oficonv_cleanup)
+{
+ OFiconv_cleanup();
+}
#endif
#if defined (DCMTK_OFLOG_UNICODE)
-# if defined (_MSC_VER) && _MSC_VER >= 1400
+# if defined (_MSC_VER)
# define DCMTK_LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T
-# endif
-# if defined (_MSC_VER) && _MSC_VER >= 1600
# define DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF8_FACET
# define DCMTK_LOG4CPLUS_HAVE_CODECVT_UTF16_FACET
# endif
# define __has_feature(X) 0
#endif
-#if (defined (_MSC_VER) && _MSC_VER >= 1600) \
- || defined (__GXX_EXPERIMENTAL_CXX0X__)
+#if defined (_MSC_VER) || defined (__GXX_EXPERIMENTAL_CXX0X__)
# define DCMTK_LOG4CPLUS_HAVE_modern_cxx_support
#endif
#endif
/* */
-#ifdef HAVE_SYS_TYPES_H
#define DCMTK_LOG4CPLUS_HAVE_SYS_TYPES_H
-#endif
/* */
-#ifdef HAVE_SYS_STAT_H
#define DCMTK_LOG4CPLUS_HAVE_SYS_STAT_H
-#endif
/* */
#ifdef HAVE_SYS_SYSCALL_H
#endif
/* */
-#ifdef HAVE_FCNTL_H
#define DCMTK_LOG4CPLUS_HAVE_FCNTL_H
-#endif
/* */
#define DCMTK_LOG4CPLUS_HAVE_STDARG_H
#endif
/* */
-#ifdef HAVE_GETPID
#define DCMTK_LOG4CPLUS_HAVE_GETPID
-#endif
/* */
#ifdef HAVE_PROTOTYPE_GETTIMEOFDAY
#endif
/* */
-#ifdef HAVE_STAT
#define DCMTK_LOG4CPLUS_HAVE_STAT
-#endif
/* */
#ifdef WITH_THREADS
#endif
/* */
-#ifdef HAVE_VSNPRINTF
#define DCMTK_LOG4CPLUS_HAVE_VSNPRINTF
-#endif
/* */
#ifdef HAVE_PROTOTYPE_STD__VSNPRINTF
#ifdef _WIN32
-/* This used to be _MSC_VER >= 1400, but MSVC 2005 is broken */
-#if (defined (_MSC_VER) && _MSC_VER > 1400)
+#ifdef _MSC_VER
# define DCMTK_LOG4CPLUS_HAVE_INTRIN_H
#endif
#define DCMTK_LOG4CPLUS_HAVE_TIME_H
#define DCMTK_LOG4CPLUS_HAVE_SYS_TIMEB_H
#define DCMTK_LOG4CPLUS_HAVE_FTIME
-#if defined (_MSC_VER) || defined (__BORLANDC__)
+#if defined (_MSC_VER) || defined (HAVE_CLASSIC_BORLAND_COMPILER)
#define DCMTK_LOG4CPLUS_HAVE_GMTIME_S
#endif
// MSVC has both and so does MinGW.
#define DCMTK_LOG4CPLUS_HAVE_VSNPRINTF
#define DCMTK_LOG4CPLUS_HAVE__VSNPRINTF
-#if _MSC_VER <= 1200 /* Additional settings for VC6 and older */
-#undef DCMTK_LOG4CPLUS_HAVE_VSNPRINTF
-#endif
// MS secure versions of vprintf().
#ifdef HAVE_VSPRINTF_S
# pragma warning( disable : 4251 )
# define DCMTK_LOG4CPLUS_INLINES_ARE_EXPORTED
-
-# if _MSC_VER >= 1400
-# define DCMTK_LOG4CPLUS_WORKING_LOCALE
-# define DCMTK_LOG4CPLUS_HAVE_FUNCTION_MACRO
-# define DCMTK_LOG4CPLUS_HAVE_FUNCSIG_MACRO
-# define DCMTK_LOG4CPLUS_HAVE_C99_VARIADIC_MACROS
-# endif
+# define DCMTK_LOG4CPLUS_WORKING_LOCALE
+# define DCMTK_LOG4CPLUS_HAVE_FUNCTION_MACRO
+# define DCMTK_LOG4CPLUS_HAVE_FUNCSIG_MACRO
+# define DCMTK_LOG4CPLUS_HAVE_C99_VARIADIC_MACROS
#endif
#if defined (__GNUC__)
#include <cstdio>
#include <stdexcept>
-#if defined (__BORLANDC__)
+#if defined (HAVE_CLASSIC_BORLAND_COMPILER)
// For _wrename() and _wremove() on Windows.
# include <stdio.h>
#endif
long const DCMTK_LOG4CPLUS_FILE_NOT_FOUND = ENOENT;
-static
+static
long
file_rename (tstring const & src, tstring const & target)
{
if (ret == 0)
{
loglog.debug (
- DCMTK_LOG4CPLUS_TEXT("Renamed file ")
- + src
+ DCMTK_LOG4CPLUS_TEXT("Renamed file ")
+ + src
+ DCMTK_LOG4CPLUS_TEXT(" to ")
+ target);
}
if (! os)
{
loglog.error (
- DCMTK_LOG4CPLUS_TEXT("Failed to open file ")
+ DCMTK_LOG4CPLUS_TEXT("Failed to open file ")
+ filename);
}
}
// FileAppender ctors and dtor
///////////////////////////////////////////////////////////////////////////////
-FileAppender::FileAppender(const tstring& filename_,
+FileAppender::FileAppender(const tstring& filename_,
STD_NAMESPACE ios_base::openmode mode_, bool immediateFlush_)
: immediateFlush(immediateFlush_)
, reopenDelay(1)
}
-FileAppender::FileAppender(const Properties& props,
+FileAppender::FileAppender(const Properties& props,
STD_NAMESPACE ios_base::openmode mode_)
: Appender(props)
, immediateFlush(true)
void
-FileAppender::init(const tstring& filename_,
+FileAppender::init(const tstring& filename_,
STD_NAMESPACE ios_base::openmode mode_,
const log4cplus::tstring& lockFileName_)
{
imbue (get_locale_by_name (localeName));
if(!out.good()) {
- getErrorHandler()->error( DCMTK_LOG4CPLUS_TEXT("Unable to open file: ")
+ getErrorHandler()->error( DCMTK_LOG4CPLUS_TEXT("Unable to open file: ")
+ filename);
return;
}
// FileAppender public methods
///////////////////////////////////////////////////////////////////////////////
-void
+void
FileAppender::close()
{
thread::MutexGuard guard (access_mutex);
{
if(!out.good()) {
if(!reopen()) {
- getErrorHandler()->error( DCMTK_LOG4CPLUS_TEXT("file is not open: ")
+ getErrorHandler()->error( DCMTK_LOG4CPLUS_TEXT("file is not open: ")
+ filename);
return;
}
- // Resets the error handler to make it
+ // Resets the error handler to make it
// ready to handle a future append error.
else
getErrorHandler()->reset();
out.close();
// Reset flags since the C++ standard specified that all the flags
// should remain unchanged on a close.
- out.clear();
+ out.clear();
if (useLockFile)
{
#endif
loglog.debug (
- DCMTK_LOG4CPLUS_TEXT("Renaming file ")
- + filename
+ DCMTK_LOG4CPLUS_TEXT("Renaming file ")
+ + filename
+ DCMTK_LOG4CPLUS_TEXT(" to ")
+ target);
ret = file_rename (filename, target);
+ properties.getProperty(DCMTK_LOG4CPLUS_TEXT("Schedule")));
theSchedule = DAILY;
}
-
+
properties.getInt (maxBackupIndex, DCMTK_LOG4CPLUS_TEXT("MaxBackupIndex"));
init(theSchedule);
// possible to rename over existing file, e.g. "log.2009-11-07".
ret = file_remove (scheduledFilename);
#endif
-
+
// Rename filename to scheduledFilename,
// e.g. rename "log" to "log.2009-11-07".
loglog.debug(
DCMTK_LOG4CPLUS_TEXT("Renaming file ")
- + filename
+ + filename
+ DCMTK_LOG4CPLUS_TEXT(" to ")
+ scheduledFilename);
ret = file_rename (filename, scheduledFilename);
{
switch(schedule)
{
- case MONTHLY:
+ case MONTHLY:
{
struct tm nextMonthTime;
t.localtime(&nextMonthTime);
{
#if defined (DCMTK_OFLOG_UNICODE)
return !! STD_NAMESPACE iswcntrl (STD_NAMESPACE char_traits<tchar>::to_int_type (ch));
-#elif defined (_MSC_VER) && _MSC_VER <= 1200 /* MSC6 and older */
- return !! iscntrl (STD_NAMESPACE char_traits<tchar>::to_int_type (ch));
#else
return !! STD_NAMESPACE iscntrl (STD_NAMESPACE char_traits<tchar>::to_int_type (ch));
#endif
#if defined(DCMTK_LOG4CPLUS_USE_PTHREADS)
sched_yield();
#elif defined(_WIN32)
-#if !defined(_MSC_VER) || _MSC_VER > 1200 /* MSC 6 doesn't know this */
if (! SwitchToThread ())
-#endif
Sleep (0);
#endif
}
Time::gmtime(tm* t) const
{
time_t clock = tv_sec;
-#if defined (DCMTK_LOG4CPLUS_HAVE_GMTIME_S) && defined (_MSC_VER) && _MSC_VER > 1200
- gmtime_s (t, &clock);
-#elif defined (DCMTK_LOG4CPLUS_HAVE_GMTIME_S) && defined (__BORLANDC__)
+#if defined (DCMTK_LOG4CPLUS_HAVE_GMTIME_S) && defined (HAVE_CLASSIC_BORLAND_COMPILER)
gmtime_s (&clock, t);
+#elif defined (DCMTK_LOG4CPLUS_HAVE_GMTIME_S) && defined (_MSC_VER)
+ gmtime_s (t, &clock);
#elif defined (DCMTK_LOG4CPLUS_NEED_GMTIME_R)
gmtime_r (&clock, t);
#else
--- /dev/null
+/* MacOS 15.5 defines some Clang specific pragmas in header files
+ * without checking if the current compiler is actually Clang.
+ * This code allows us to suppress warnings when compiling with GCC
+ */
+#if defined(__APPLE__) && defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#endif
--- /dev/null
+// Visual Studio warns if a certain expression is constant
+// i.e. known at compile time and used in a conditional statement.
+// In C++17 constexpr should be used then but we don't want a warning
+// about it.
+#ifdef _MSC_VER
+#pragma warning(disable: 4127)
+#endif
\ No newline at end of file
/*
*
- * Copyright (C) 2011-2018, OFFIS e.V.
+ * Copyright (C) 2011-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* @remark This list of code pages is only available if DCMTK is compiled
* on Windows Operating Systems (defining _WIN32)
*/
- //@{
+ ///@{
/// system default Windows ANSI code page. See Windows function GetACP().
/// @remark Only available on Windows Operating Systems (defining _WIN32).
/// @remark Only available on Windows Operating Systems (defining _WIN32).
static const unsigned int CPC_UTF8;
- //@}
+ ///@}
// --- static Windows-specific functions ---
/*
*
- * Copyright (C) 1998-2021, OFFIS e.V.
+ * Copyright (C) 1998-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* macro definition *
*--------------------*/
-// Only use wchar_t on windows (not mingw) and don't use it on MSC6
-#if defined(HAVE_WINDOWS_H) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER > 1200)
+// Only use wchar_t on windows (not mingw)
+#if defined(HAVE_WINDOWS_H) && !defined(__MINGW32__)
# define DCMTK_USE_WCHAR_T
#endif
#if defined(WIDE_CHAR_MAIN_FUNCTION) && defined(DCMTK_USE_WCHAR_T)
/*
*
- * Copyright (C) 2001-2023, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
* All constants defined here use module number 0, which is reserved for
* global definitions. Other constants are defined in other modules.
*/
-//@{
+///@{
+
/// condition constant: successful completion
extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_Normal;
/// condition constant: error, function called with illegal parameters
/// condition constant: error, IPC message empty (zero length)
extern DCMTK_OFSTD_EXPORT const OFConditionConst EC_IPCEmptyMessage;
-//@}
+///@}
/** use this macro for creating static OFCondition instances. Instead of an
/*
*
- * Copyright (C) 2002-2017, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h"
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h> /* for struct time_t */
-#endif
+#include <sys/types.h> /* for struct time_t */
END_EXTERN_C
#include "dcmtk/ofstd/ofstring.h" /* for class OFString */
#define DCMTK_DIAGNOSTIC_IGNORE_USE_AFTER_FREE "dcmtk/ofstd/diag/useafree.def"
#define DCMTK_DIAGNOSTIC_IGNORE_ARRAY_BOUNDS "dcmtk/ofstd/diag/arrybnds.def"
#define DCMTK_DIAGNOSTIC_IGNORE_UNSIGNED_UNARY_MINUS "dcmtk/ofstd/diag/unarymin.def"
+#define DCMTK_DIAGNOSTIC_IGNORE_CLANG_PRAGMAS_ON_GCC "dcmtk/ofstd/diag/clangprg.def"
+#define DCMTK_DIAGNOSTIC_IGNORE_VISUAL_STUDIO_CONSTANT_EXPRESSION_WARNING "dcmtk/ofstd/diag/vsconstexp.def"
// readable shorthands for compiler version checks
#define DCMTK_DIAGNOSTIC_MIN_GCC_VERSION(MAJOR, MINOR, PATCH)\
/*
*
- * Copyright (C) 2006-2024, OFFIS e.V.
+ * Copyright (C) 2006-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include <cerrno>
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* needed for struct _stati64 on Win32 */
-#endif
END_EXTERN_C
#ifdef HAVE_UNIX_H
// Use POSIX 64 bit file offset type when available
#ifdef HAVE_OFF64_T
typedef off64_t offile_off_t;
-#elif !defined(OF_NO_SINT64) // Otherwise use a 64 bit integer
+#else
+// Otherwise use a 64 bit integer
typedef Sint64 offile_off_t;
-#else // Cry when 64 LFS is required but no 64 bit integer exists
-#error \
- Could not find a suitable offset-type for LFS64 support.
#endif
#else // Implicit LFS or no LFS
#if defined(DCMTK_ENABLE_LFS) && DCMTK_ENABLE_LFS == DCMTK_LFS
#if defined(SIZEOF_FPOS_T) && (!defined(SIZEOF_OFF_T) || SIZEOF_FPOS_T > SIZEOF_OFF_T)
-// strange Windows LFS where sizeof(fpos_t) == 8 but sizeof(off_t) == 4
-#ifndef OF_NO_SINT64 // Use a 64 bit integer
+// strange Windows LFS where sizeof(fpos_t) == 8 but sizeof(off_t) == 4. Use a 64 bit integer
typedef Sint64 offile_off_t;
-#else // Cry when LFS is required but no 64 bit integer exists
-#error \
- Could not find a suitable offset-type for LFS support.
-#endif
#else
typedef off_t offile_off_t;
#endif
--- /dev/null
+/*
+ * MIT License
+ *
+ * Copyright (c) 2010 Serge Zaitsev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef OFJSMN_H
+#define OFJSMN_H
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/oftypes.h"
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef JSMN_STATIC
+#define JSMN_API static
+#else
+#define JSMN_API extern DCMTK_OFSTD_EXPORT
+#endif
+
+/**
+ * JSON type identifier. Basic types are:
+ * o Object
+ * o Array
+ * o String
+ * o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+ JSMN_UNDEFINED = 0,
+ JSMN_OBJECT = 1 << 0,
+ JSMN_ARRAY = 1 << 1,
+ JSMN_STRING = 1 << 2,
+ JSMN_PRIMITIVE = 1 << 3
+} jsmntype_t;
+
+enum jsmnerr {
+ /* Not enough tokens were provided */
+ JSMN_ERROR_NOMEM = -1,
+ /* Invalid character inside JSON string */
+ JSMN_ERROR_INVAL = -2,
+ /* The string is not a full JSON packet, more bytes expected */
+ JSMN_ERROR_PART = -3
+};
+
+/**
+ * JSON token description.
+ * type type (object, array, string etc.)
+ * start start position in JSON data string
+ * end end position in JSON data string
+ */
+typedef struct jsmntok {
+ jsmntype_t type;
+ int start;
+ int end;
+ int size;
+#ifdef JSMN_PARENT_LINKS
+ int parent;
+#endif
+} jsmntok_t;
+
+/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string.
+ */
+typedef struct jsmn_parser {
+ unsigned int pos; /* offset in the JSON string */
+ unsigned int toknext; /* next token to allocate */
+ int toksuper; /* superior token node, e.g. parent object or array */
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+JSMN_API void jsmn_init(jsmn_parser *parser);
+
+/**
+ * Run JSON parser. It parses a JSON data string into and array of tokens, each
+ * describing
+ * a single JSON object.
+ */
+JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
+ jsmntok_t *tokens, const unsigned int num_tokens);
+
+#ifndef JSMN_HEADER
+/**
+ * Allocates a fresh unused token from the token pool.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens,
+ const size_t num_tokens) {
+ jsmntok_t *tok;
+ if (parser->toknext >= num_tokens) {
+ return NULL;
+ }
+ tok = &tokens[parser->toknext++];
+ tok->start = tok->end = -1;
+ tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+ tok->parent = -1;
+#endif
+ return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type,
+ const int start, const int end) {
+ token->type = type;
+ token->start = start;
+ token->end = end;
+ token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+ const size_t len, jsmntok_t *tokens,
+ const size_t num_tokens) {
+ jsmntok_t *token;
+ int start;
+
+ start = parser->pos;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+ /* In strict mode primitive must be followed by "," or "}" or "]" */
+ case ':':
+#endif
+ case '\t':
+ case '\r':
+ case '\n':
+ case ' ':
+ case ',':
+ case ']':
+ case '}':
+ goto found;
+ default:
+ /* to quiet a warning from gcc*/
+ break;
+ }
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#ifdef JSMN_STRICT
+ /* In strict mode primitive must be followed by a comma/object/array */
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+#endif
+
+found:
+ if (tokens == NULL) {
+ parser->pos--;
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ parser->pos--;
+ return 0;
+}
+
+/**
+ * Fills next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+ const size_t len, jsmntok_t *tokens,
+ const size_t num_tokens) {
+ jsmntok_t *token;
+
+ int start = parser->pos;
+
+ /* Skip starting quote */
+ parser->pos++;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c = js[parser->pos];
+
+ /* Quote: end of string */
+ if (c == '\"') {
+ if (tokens == NULL) {
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ return 0;
+ }
+
+ /* Backslash: Quoted symbol expected */
+ if (c == '\\' && parser->pos + 1 < len) {
+ int i;
+ parser->pos++;
+ switch (js[parser->pos]) {
+ /* Allowed escaped symbols */
+ case '\"':
+ case '/':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'r':
+ case 'n':
+ case 't':
+ break;
+ /* Allows escaped symbol \uXXXX */
+ case 'u':
+ parser->pos++;
+ for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0';
+ i++) {
+ /* If it isn't a hex character we have an error */
+ if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ parser->pos++;
+ }
+ parser->pos--;
+ break;
+ /* Unexpected symbol */
+ default:
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+ }
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len,
+ jsmntok_t *tokens, const unsigned int num_tokens) {
+ int r;
+ int i;
+ jsmntok_t *token;
+ int count = parser->toknext;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c;
+ jsmntype_t type;
+
+ c = js[parser->pos];
+ switch (c) {
+ case '{':
+ case '[':
+ count++;
+ if (tokens == NULL) {
+ break;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ return JSMN_ERROR_NOMEM;
+ }
+ if (parser->toksuper != -1) {
+ jsmntok_t *t = &tokens[parser->toksuper];
+#ifdef JSMN_STRICT
+ /* In strict mode an object or array can't become a key */
+ if (t->type == JSMN_OBJECT) {
+ return JSMN_ERROR_INVAL;
+ }
+#endif
+ t->size++;
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ }
+ token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+ token->start = parser->pos;
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case '}':
+ case ']':
+ if (tokens == NULL) {
+ break;
+ }
+ type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+ if (parser->toknext < 1) {
+ return JSMN_ERROR_INVAL;
+ }
+ token = &tokens[parser->toknext - 1];
+ for (;;) {
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ token->end = parser->pos + 1;
+ parser->toksuper = token->parent;
+ break;
+ }
+ if (token->parent == -1) {
+ if (token->type != type || parser->toksuper == -1) {
+ return JSMN_ERROR_INVAL;
+ }
+ break;
+ }
+ token = &tokens[token->parent];
+ }
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ parser->toksuper = -1;
+ token->end = parser->pos + 1;
+ break;
+ }
+ }
+ /* Error if unmatched closing bracket */
+ if (i == -1) {
+ return JSMN_ERROR_INVAL;
+ }
+ for (; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+#endif
+ break;
+ case '\"':
+ r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+ if (r < 0) {
+ return r;
+ }
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL) {
+ tokens[parser->toksuper].size++;
+ }
+ break;
+ case '\t':
+ case '\r':
+ case '\n':
+ case ' ':
+ break;
+ case ':':
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case ',':
+ if (tokens != NULL && parser->toksuper != -1 &&
+ tokens[parser->toksuper].type != JSMN_ARRAY &&
+ tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+ parser->toksuper = tokens[parser->toksuper].parent;
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ break;
+#ifdef JSMN_STRICT
+ /* In strict mode primitives are: numbers and booleans */
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case 't':
+ case 'f':
+ case 'n':
+ /* And they must not be keys of the object */
+ if (tokens != NULL && parser->toksuper != -1) {
+ const jsmntok_t *t = &tokens[parser->toksuper];
+ if (t->type == JSMN_OBJECT ||
+ (t->type == JSMN_STRING && t->size != 0)) {
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#else
+ /* In non-strict mode every unquoted value is a primitive */
+ default:
+#endif
+ r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+ if (r < 0) {
+ return r;
+ }
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL) {
+ tokens[parser->toksuper].size++;
+ }
+ break;
+
+#ifdef JSMN_STRICT
+ /* Unexpected char in strict mode */
+ default:
+ return JSMN_ERROR_INVAL;
+#endif
+ }
+ }
+
+ if (tokens != NULL) {
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ /* Unmatched opened object or array */
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ return JSMN_ERROR_PART;
+ }
+ }
+ }
+
+ return count;
+}
+
+/**
+ * Creates a new parser based over a given buffer with an array of tokens
+ * available.
+ */
+JSMN_API void jsmn_init(jsmn_parser *parser) {
+ parser->pos = 0;
+ parser->toknext = 0;
+ parser->toksuper = -1;
+}
+
+#endif /* JSMN_HEADER */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OFJSMN_H */
/*
*
- * Copyright (C) 1997-2024, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// of one class of the STL
#include <list>
-#ifdef HAVE_STD_NAMESPACE
#define OFList std::list
#define OFListIterator(x) std::list< x >::iterator
#define OFListConstIterator(x) std::list< x >::const_iterator
-#else
-#define OFList list
-#define OFListIterator(x) list< x >::iterator
-#define OFListConstIterator(x) list< x >::const_iterator
-#endif
-
#define OFListInsert(InputIterator, T, c, pos, first, last) (c).insert((pos), (first), (last))
#define OFListRemoveIf(Predicate, T, c, pred) (c).remove_if((pred))
#define OFLIST_TYPENAME
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
/* needed e.g. on Solaris for definition of size_t */
#include <sys/types.h>
-#endif
END_EXTERN_C
// OFListLinkBase, OFListLink and OFListBase are classes for internal
/*
*
- * Copyright (C) 2015, OFFIS e.V.
+ * Copyright (C) 2015-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
static OFBool (isinf) (float f);
static OFBool (isinf) (double d);
+ static double (sqrt) (double d);
template<typename Integer>
static inline OFTypename OFenable_if<OFis_integral<Integer>::value,OFBool>::type
(isinf) ( const Integer i ) { return (isinf) ( OFstatic_cast( double, i ) ); }
*/
static OFBool isinf( double d );
+ /** Computes the square root of a floating point number.
+ * @param d the floating point value to inspect.
+ * @return the square root of d.
+ */
+ static double sqrt( double d );
+
/** Casts the argument to double and calls OFMath::isinf(double) on the result.
* @param i an integer, i.e. <kbd>OFis_integral<Integer>::value</kbd> equals <kbd>OFTrue</kbd>.
* @return OFMath::isinf(OFstatic_cast(double,i)).
/*
*
- * Copyright (C) 2012-2017, OFFIS e.V.
+ * Copyright (C) 2012-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#if defined HAVE_SYNC_ADD_AND_FETCH && defined HAVE_SYNC_SUB_AND_FETCH
#define OF_SHARED_PTR_COUNTER_TYPE size_t
#elif defined HAVE_INTERLOCKED_INCREMENT && defined HAVE_INTERLOCKED_DECREMENT
-#if _MSC_VER <= 1200
-#define OF_SHARED_PTR_COUNTER_TYPE LONG
-#else
#define OF_SHARED_PTR_COUNTER_TYPE volatile LONG
-#endif
#else
#define OF_SHARED_PTR_COUNTER_TYPE size_t
#define OF_SHARED_PTR_NEED_MUTEX 1
// include <type_traits> for "std::is_default_constructible"
// to recover from compiler insanity (Visual Studio 12+).
-#if defined(_MSC_VER) && _MSC_VER >= 1700
+#if defined(_MSC_VER)
#include <type_traits>
#endif
template<typename X>
static yes_type sfinae(consume<sizeof *new X>*);
#elif defined(_MSC_VER)
-#if _MSC_VER < 1700
- // Workaround bug in Visual Studio.
- // On these broken compilers, the argument is not evaluated
- // unless we require them to evaluate it for choosing which
- // specialization should be instantiated.
- template<size_t,size_t>
- struct consume{};
- template<size_t X>
- struct consume<X,X> { typedef void type; };
- // sfinae overload working for value-initializable Xs, that's as
- // close as we get on these broken compilers
- template<typename X>
- static yes_type sfinae(typename consume<sizeof X(),sizeof X()>::type*);
-#else
// Visual Studio 2012 is completely broken, but it has std::is_default_constructible
// Note: this tests constructibility, but not if WE can construct this.
template<typename X>
static yes_type sfinae(typename OFenable_if<std::is_default_constructible<X>::value>::type*);
-#endif // _MSC_VER
#endif // HAVE_DEFAULT_CONSTRUCTOR_DETECTION_VIA_SFINAE
// most general sfinae overload, chosen only if everything else fails
template<typename X>
/*
*
- * Copyright (C) 2018, OFFIS e.V.
+ * Copyright (C) 2018-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
/// destructor
virtual ~OFRandom() {}
-#ifndef OF_NO_UINT64
/** return a random Uint64 value
* @return random unsigned 64-bit number
*/
Uint64 getRND64();
-#endif
/** return a random Uint32 value
* @return random unsigned 32-bit number
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: ofstd
+ *
+ * Author: Marco Eichelberg, based on code by Brad Conte (brad AT bradconte.com) in FreeBSD
+ *
+ * Purpose: Implementation of SHA-256
+ *
+ */
+
+#ifndef OFSHA256_H
+#define OFSHA256_H
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/ofdefine.h"
+#include "dcmtk/ofstd/oftypes.h"
+
+
+#define SHA256_BLOCK_SIZE 32 // SHA-256 outputs a 32 byte digest
+
+class DCMTK_OFSTD_EXPORT OFSHA256
+{
+public:
+ /// default constructor
+ OFSHA256();
+
+ /// initialize instance, i.e. reset to initial state
+ void init();
+
+ /** feed bytes to the hash algorithm
+ * @param data bytes to feed
+ * @param len number of bytes
+ */
+ void update(const void *data, size_t len);
+
+ /** finalize and return hash
+ * @param hash pointer to memory block of at least 32 bytes.
+ * The SHA-256 hash is copied into this block.
+ */
+ void final(void *hash);
+
+private:
+
+ /// transform hash key state based on the content of the data buffer
+ void transform();
+
+ /// data buffer
+ Uint8 data_[64];
+
+ /// number of bytes in data buffer
+ Uint32 datalen_;
+
+ /// total number of bits that have been fed into the hash algorithm
+ unsigned long long bitlen_;
+
+ /// state information for the hash key
+ Uint32 state_[8];
+};
+
+#endif
/*
*
- * Copyright (C) 2017-2021, OFFIS e.V.
+ * Copyright (C) 2017-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#endif
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_SOCKET_H
/* some systems (such as DEC Ultrix) don't protect <sys/socket.h> from double inclusion */
#ifndef DCOMPAT_SYS_SOCKET_H_
struct sockaddr_in;
struct sockaddr_in6;
-/** A simple wrapper class for a struct sockaddr_storage object
+/** A simple wrapper class for a struct sockaddr_storage object
* that can be used to store an TCP/IPv4 (struct sockaddr_in) or TCP/IPv6
* (struct sockaddr_in6) address.
*/
/*
*
- * Copyright (C) 2000-2024, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#endif
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* for size_t */
-#endif
END_EXTERN_C
/* Check if we are using glibc in a version where readdir() is known to be
* thread-safe and where readdir_r() is deprecated.
+ * Android uses a different libc implementation but also guarantees that
+ * readdir() is thread-safe and marks readdir_r() as deprecated.
*/
-#if defined(__GLIBC__) && (((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 24)) || (__GLIBC__ >= 3))
+#if (defined(__GLIBC__) && (((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 24)) || (__GLIBC__ >= 3))) || defined(__ANDROID__)
#define READDIR_IS_THREADSAFE
#endif
* can be decoded back to its exact size.
* If the input data is NULL an error code (EC_IllegalParameter) is returned.
** @param out output stream used for the base64 encoded data
- * @param data buffer with binary data to be encoded (big endian required!)
+ * @param data buffer with binary data to be encoded
* @param length length of the input data buffer (in bytes)
* @param width maximum number of characters per line in the output stream
* (default: 0 = no line breaks, typical for MIME = 72)
* even multiple of 3. A special character ('=') is used to denote padding so that the output
* can be decoded back to its exact size.
* If the input data is NULL an empty string is returned.
- ** @param data buffer with binary data to be encoded (big endian required!)
+ ** @param data buffer with binary data to be encoded
* @param length length of the input data buffer (in bytes)
* @param result reference to resulting string variable (Base64 encoded)
* @param width maximum number of characters per line in the output string
* and has to to be freed (using "delete[]") by the caller! Do not pass a pointer to an
* already allocated buffer to this function, the caller does not know the exact size anyway.
** @param data Base64 encoded input data (possibly padded with '=' at the end)
- * @param result receives pointer to resulting buffer with binary data (big endian encoded)
+ * @param result receives pointer to resulting buffer with binary data
** @return length of the resulting binary data (0 if an error occurred, in this case the buffer
* is deleted internally)
*/
/** @name ftoa() processing flags.
* These flags can be combined by bit-wise or.
*/
- //@{
+ ///@{
/// Use scientific format (equivalent to %e or %E in printf),
/// instead of the default, which is equivalent to %g or %G.
/// pad with zeroes instead of blanks
static const unsigned int ftoa_zeropad;
- //@}
+ ///@}
/** makes the current process sleep until seconds seconds have
* elapsed or a signal arrives which is not ignored
/*
*
- * Copyright (C) 2002-2021, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// define STD_NAMESPACE to std:: if the standard namespace exists
#ifndef STD_NAMESPACE
-#ifdef HAVE_STD_NAMESPACE
#define STD_NAMESPACE std::
-#else
-#define STD_NAMESPACE
-#endif
#endif
/* Print an error message in case some user code still uses the now unsupported
/*
*
- * Copyright (C) 2002-2024, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// define STD_NAMESPACE to std:: if the standard namespace exists
#ifndef STD_NAMESPACE
-#ifdef HAVE_STD_NAMESPACE
#define STD_NAMESPACE std::
-#else
-#define STD_NAMESPACE
-#endif
#endif
#define OFendl STD_NAMESPACE endl
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: ofstd
+ *
+ * Author: Marco Eichelberg
+ *
+ * Purpose: Helper functions to convert between std::string and OFString
+ *
+ */
+
+#ifndef OFSTRHLP_H
+#define OFSTRHLP_H
+
+#include "dcmtk/config/osconfig.h" /* include OS specific configuration first */
+#include "dcmtk/ofstd/ofstring.h" /* for class OFString */
+#include <string> /* for std::string */
+
+/** convert OFString to std::string.
+ * This helper function converts an OFString object into an equivalent std::string.
+ * @param arg string to convert
+ * @return string as std::string object
+ */
+inline STD_NAMESPACE string OFString_to_std_string(const OFString& arg)
+{
+#ifdef HAVE_STL_STRING
+ // OFString is just a typedef for std::string
+ return arg;
+#else
+ return STD_NAMESPACE string(arg.c_str(), arg.length());
+#endif
+}
+
+/** convert std::string to OFString.
+ * This helper function converts a std::string object into an equivalent OFString.
+ * @param arg string to convert
+ * @return string as OFString object
+ */
+inline OFString std_string_to_OFString(const STD_NAMESPACE string& arg)
+{
+#ifdef HAVE_STL_STRING
+ // OFString is just a typedef for std::string
+ return arg;
+#else
+ return OFString(arg.c_str(), arg.length());
+#endif
+}
+
+#endif /* OFSTRHLP_H */
/*
*
- * Copyright (C) 2011-2016, OFFIS e.V.
+ * Copyright (C) 2011-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/ofstd/oftypes.h" /* for OFBool */
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for O_RDWR */
-#endif
-#ifdef HAVE_FCNTL_H
#include <fcntl.h> /* needed on Solaris for O_RDWR */
-#endif
END_EXTERN_C
/** this class manages the lifetime of a temporary file. The file will be
/*
*
- * Copyright (C) 2011-2022, OFFIS e.V.
+ * Copyright (C) 2011-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This code is inspired by quicktest.
* These macros can be used for doing various checks in test cases. In case
* their check fails, they emit a descriptive message explaining the problem.
*/
-//@{
+///@{
/** Check if a condition is true. Can only be used inside OFTEST().
* @param condition condition to check
OFTestManager::instance().currentTest().recordFailure(__FILE__, __LINE__, str___); \
} while (0)
-//@}
+///@}
#endif
/*
*
- * Copyright (C) 2002-2021, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h"
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h> /* for struct time_t */
-#endif
+#include <sys/types.h> /* for struct time_t */
END_EXTERN_C
#include "dcmtk/ofstd/ofstring.h" /* for class OFString */
/*
*
- * Copyright (C) 1997-2024, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include <cstddef>
BEGIN_EXTERN_C
-#ifdef HAVE_STDINT_H
#include <stdint.h>
-#endif
#include <inttypes.h>
END_EXTERN_C
typedef OFlonglong Sint64;
#else
/* we have not found any 64-bit signed integer type */
-#define OF_NO_SINT64 1
+#error unsupported platform (no 64-bit signed integer type)
#endif
#ifdef HAVE_UINT64_T
typedef OFulonglong Uint64;
#else
/* we have not found any 64-bit unsigned integer type */
-#define OF_NO_UINT64 1
+#error unsupported platform (no 64-bit unsigned integer type)
#endif
#if SIZEOF_VOID_P == 2
typedef Sint32 OFintptr_t;
typedef Uint32 OFuintptr_t;
#elif SIZEOF_VOID_P == 8
-#ifndef OF_NO_SINT64
typedef Sint64 OFintptr_t;
-#else
-#error unsupported platform (64-Bit pointers but no 64-Bit signed integer type)
-#endif
-#ifndef OF_NO_UINT64
typedef Uint64 OFuintptr_t;
#else
-#error unsupported platform (64-Bit pointers but no 64-Bit unsigned integer type)
-#endif
-#else
#error Unsupported platform (invalid pointer size)
#endif
/*
*
- * Copyright (C) 2010-2024, OFFIS e.V.
+ * Copyright (C) 2010-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
// Use the standard template library (STL) vector class.
#include <vector>
-
-#ifdef HAVE_STD_NAMESPACE
#define OFVector std::vector
-#else
-#define OFVector vector
-#endif
#else
# create library from source files
-DCMTK_ADD_LIBRARY(ofstd
+DCMTK_ADD_LIBRARY(ofstd
ofchrenc.cc
ofcmdln.cc
ofconapp.cc
offilsys.cc
offname.cc
ofipc.cc
+ ofjsmn.cc
oflist.cc
ofstd.cc
ofstring.cc
ofrand.cc
ofwhere.c
ofstub.cc
+ ofsha256.cc
)
DCMTK_TARGET_LINK_LIBRARIES(ofstd config ${CHARSET_CONVERSION_LIBS} ${SOCKET_LIBS} ${THREAD_LIBS} ${WIN32_STD_LIBRARIES})
../include/dcmtk/ofstd/oflist.h ../include/dcmtk/ofstd/ofstd.h \
../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/oflimits.h \
../include/dcmtk/ofstd/oferror.h
+ofjsmn.o: ofjsmn.cc ../include/dcmtk/ofstd/ofjsmn.h \
+ ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/ofstd/oftypes.h ../include/dcmtk/ofstd/ofdefine.h \
+ ../include/dcmtk/ofstd/ofcast.h ../include/dcmtk/ofstd/ofexport.h \
+ ../include/dcmtk/ofstd/ofstdinc.h
oflist.o: oflist.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/ofstd/oflist.h ../include/dcmtk/ofstd/oftypes.h \
../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \
../include/dcmtk/ofstd/diag/useafree.def \
../include/dcmtk/ofstd/diag/pop.def ../include/dcmtk/ofstd/oflimits.h \
../include/dcmtk/ofstd/oferror.h
+ofsha256.o: ofsha256.cc ../../config/include/dcmtk/config/osconfig.h \
+ ../include/dcmtk/ofstd/ofsha256.h ../include/dcmtk/ofstd/ofdefine.h \
+ ../include/dcmtk/ofstd/ofcast.h ../include/dcmtk/ofstd/ofexport.h \
+ ../include/dcmtk/ofstd/oftypes.h ../include/dcmtk/ofstd/ofstdinc.h
ofsockad.o: ofsockad.cc ../../config/include/dcmtk/config/osconfig.h \
../include/dcmtk/ofstd/ofsockad.h ../include/dcmtk/ofstd/ofdefine.h \
../include/dcmtk/ofstd/ofcast.h ../include/dcmtk/ofstd/ofexport.h \
ofcond.o ofstd.o ofcrc32.o ofdate.o oftime.o ofdatime.o oftimer.o \
ofconfig.o ofchrenc.o oftempf.o ofxml.o ofuuid.o offile.o offilsys.o \
ofmath.o oferror.o ofsockad.o ofrand.o ofstrutl.o ofipc.o ofwhere.o \
- ofstub.o
+ ofstub.o ofsha256.o ofjsmn.o
library = libofstd.$(LIBEXT)
/*
*
- * Copyright (C) 2000-2021, OFFIS e.V.
+ * Copyright (C) 2000-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
BEGIN_EXTERN_C
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
}
}
-#ifndef __BORLANDC__ /* setvbuf on stdout/stderr does not work with Borland C++ */
+#ifndef HAVE_CLASSIC_BORLAND_COMPILER /* setvbuf on stdout/stderr does not work with Borland C++ */
/* set stdout and stderr to unbuffered mode */
if (setvbuf(stdout, NULL, _IONBF, 0 ) != 0 )
{
OFConsole::instance().lockCerr() << "Unable to switch stderr to unbuffered mode" << OFendl;
OFConsole::instance().unlockCerr();
}
-#endif /* __BORLANDC__ */
+#endif /* HAVE_CLASSIC_BORLAND_COMPILER */
}
OFConsole::instance().unlockCerr();
}
-#ifndef __BORLANDC__
+#ifndef HAVE_CLASSIC_BORLAND_COMPILER
/* switch stdout to buffered mode */
if (setvbuf(stdout, NULL, _IOFBF, BUFSIZ ) != 0 )
{
OFConsole::instance().unlockCerr();
}
-#endif /* __BORLANDC__ */
+#endif /* HAVE_CLASSIC_BORLAND_COMPILER */
}
}
/*
*
- * Copyright (C) 2002-2021, OFFIS e.V.
+ * Copyright (C) 2002-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h"
-#ifdef HAVE_SYS_TYPES_H
BEGIN_EXTERN_C
#include <sys/types.h> /* for struct time_t */
END_EXTERN_C
-#endif
#include "dcmtk/ofstd/ofdatime.h"
#include "dcmtk/ofstd/ofstdinc.h"
/*
*
- * Copyright (C) 2021-2024, OFFIS e.V.
+ * Copyright (C) 2021-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include <io.h>
#else // _WIN32
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h> // for struct DIR, opendir()
#endif
END_EXTERN_C
/* Check if we are using glibc in a version where readdir() is known to be
* thread-safe and where readdir_r() is deprecated.
+ * Android uses a different libc implementation but also guarantees that
+ * readdir() is thread-safe and marks readdir_r() as deprecated.
*/
-#if defined(__GLIBC__) && (((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 24)) || (__GLIBC__ >= 3))
+#if (defined(__GLIBC__) && (((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 24)) || (__GLIBC__ >= 3))) || defined(__ANDROID__)
#define READDIR_IS_THREADSAFE
#endif
#endif // _WIN32
/*
*
- * Copyright (C) 1997-2022, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* for time_t */
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for stat() */
-#endif
END_EXTERN_C
/* give up after this number of unsuccessful attempts to create a unique filename */
/*
*
- * Copyright (C) 2022-2024, OFFIS e.V.
+ * Copyright (C) 2022-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#if defined(HAVE_MQUEUE_H) && !defined(__FreeBSD__)
#include <mqueue.h>
#endif
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
-#endif
#ifdef HAVE_SYS_MSG_H
#include <sys/msg.h>
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
-#endif
#ifdef DCMTK_HAVE_POLL
#include <poll.h>
--- /dev/null
+/*
+ *
+ * Copyright (C) 2024-2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: ofstd
+ *
+ * Author: Tingyan Xu
+ *
+ * Purpose: Implementation of JSON parser library
+ *
+ */
+
+#include "dcmtk/ofstd/ofjsmn.h"
/*
*
- * Copyright (C) 2015-2016, OFFIS e.V.
+ * Copyright (C) 2015-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
{
return (dcmtk_config_math::isinf)( d );
}
+
+double OFMath::sqrt(double d)
+{
+ return (dcmtk_config_math::sqrt)( d );
+}
/*
*
- * Copyright (C) 2021, OFFIS e.V.
+ * Copyright (C) 2021-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
return OFstatic_cast(Uint16, getRND32());
}
-#ifndef OF_NO_UINT64
Uint64 OFRandom::getRND64()
{
// get a 32-bit random number
result |= getRND32();
return result;
}
-#endif
--- /dev/null
+/*
+ *
+ * Copyright (C) 2025, OFFIS e.V.
+ * All rights reserved. See COPYRIGHT file for details.
+ *
+ * This software and supporting documentation were developed by
+ *
+ * OFFIS e.V.
+ * R&D Division Health
+ * Escherweg 2
+ * D-26121 Oldenburg, Germany
+ *
+ *
+ * Module: ofstd
+ *
+ * Author: Marco Eichelberg, based on code by Brad Conte (brad AT bradconte.com) in FreeBSD.
+ * Disclaimer: This code is presented "as is" without any guarantees.
+ * Details: Implementation of the SHA-256 hashing algorithm.
+ * SHA-256 is one of the three algorithms in the SHA2
+ * specification. The others, SHA-384 and SHA-512, are not
+ * offered in this implementation.
+ * Algorithm specification can be found here:
+ * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
+ * This implementation internally uses little endian byte order.
+ */
+
+#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
+#include "dcmtk/ofstd/ofsha256.h"
+#include <cstring>
+
+#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
+#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
+#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
+#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
+#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
+#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
+
+static const Uint32 k[64] = {
+ 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
+ 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
+ 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
+ 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
+ 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
+ 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
+ 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
+ 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+};
+
+
+void OFSHA256::transform()
+{
+ Uint32 a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
+
+ for (i = 0, j = 0; i < 16; ++i, j += 4)
+ m[i] = (OFstatic_cast(Uint32, data_[j]) << 24) | (OFstatic_cast(Uint32, data_[j + 1]) << 16) | (OFstatic_cast(Uint32, data_[j + 2]) << 8) | (OFstatic_cast(Uint32, data_[j + 3]));
+ for ( ; i < 64; ++i)
+ m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
+
+ a = state_[0];
+ b = state_[1];
+ c = state_[2];
+ d = state_[3];
+ e = state_[4];
+ f = state_[5];
+ g = state_[6];
+ h = state_[7];
+
+ for (i = 0; i < 64; ++i) {
+ t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
+ t2 = EP0(a) + MAJ(a,b,c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + t1;
+ d = c;
+ c = b;
+ b = a;
+ a = t1 + t2;
+ }
+
+ state_[0] += a;
+ state_[1] += b;
+ state_[2] += c;
+ state_[3] += d;
+ state_[4] += e;
+ state_[5] += f;
+ state_[6] += g;
+ state_[7] += h;
+}
+
+
+OFSHA256::OFSHA256()
+{
+ init();
+}
+
+void OFSHA256::init()
+{
+ datalen_ = 0;
+ bitlen_ = 0;
+ state_[0] = 0x6a09e667;
+ state_[1] = 0xbb67ae85;
+ state_[2] = 0x3c6ef372;
+ state_[3] = 0xa54ff53a;
+ state_[4] = 0x510e527f;
+ state_[5] = 0x9b05688c;
+ state_[6] = 0x1f83d9ab;
+ state_[7] = 0x5be0cd19;
+}
+
+void OFSHA256::update(const void *data, size_t len)
+{
+ if (data == NULL) return;
+ const Uint8 *uint8data = OFreinterpret_cast(const Uint8 *, data);
+ for (size_t i = 0; i < len; ++i) {
+ data_[datalen_] = uint8data[i];
+ datalen_++;
+ if (datalen_ == 64) {
+ transform();
+ bitlen_ += 512;
+ datalen_ = 0;
+ }
+ }
+}
+
+void OFSHA256::final(void *hash)
+{
+ if (hash == NULL) return;
+
+ Uint8 *uint8hash = OFreinterpret_cast(Uint8 *, hash);
+ Uint32 i, j;
+ i = datalen_;
+
+ // Pad whatever data is left in the buffer.
+ if (datalen_ < 56) {
+ data_[i++] = 0x80;
+ while (i < 56)
+ data_[i++] = 0x00;
+ }
+ else {
+ data_[i++] = 0x80;
+ while (i < 64)
+ data_[i++] = 0x00;
+ transform();
+ memset(data_, 0, 56);
+ }
+
+ // Append to the padding the total message's length in bits and transform.
+ bitlen_ += datalen_ * 8;
+ data_[63] = OFstatic_cast(Uint8, bitlen_);
+ data_[62] = OFstatic_cast(Uint8,(bitlen_ >> 8));
+ data_[61] = OFstatic_cast(Uint8,(bitlen_ >> 16));
+ data_[60] = OFstatic_cast(Uint8,(bitlen_ >> 24));
+ data_[59] = OFstatic_cast(Uint8,(bitlen_ >> 32));
+ data_[58] = OFstatic_cast(Uint8,(bitlen_ >> 40));
+ data_[57] = OFstatic_cast(Uint8,(bitlen_ >> 48));
+ data_[56] = OFstatic_cast(Uint8,(bitlen_ >> 56));
+ transform();
+
+ // Since this implementation uses little endian byte ordering and SHA uses big endian,
+ // reverse all the bytes when copying the final state to the output hash.
+ for (i = j = 0; i < 8; ++i, ++j) {
+ uint8hash[j++] = (state_[i] >> 24) & 0xff;
+ uint8hash[j++] = (state_[i] >> 16) & 0xff;
+ uint8hash[j++] = (state_[i] >> 8) & 0xff;
+ uint8hash[j] = state_[i] & 0xff;
+ }
+}
/*
*
- * Copyright (C) 2001-2024, OFFIS e.V.
+ * Copyright (C) 2001-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include <sstream>
BEGIN_EXTERN_C
-#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> /* for stat() */
-#endif
#ifdef HAVE_IO_H
#include <io.h> /* for access() on Win32 */
#endif
-#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> /* for opendir() and closedir() */
-#endif
#ifdef HAVE_DIRENT_H
#include <dirent.h> /* for opendir() and closedir() */
#else
#if !defined(ENABLE_OLD_OFSTD_FTOA_IMPLEMENTATION) && !defined(ENABLE_IOSTREAM_BASED_FTOA_IMPLEMENTATION) && !defined(ENABLE_CSTDIO_BASED_FTOA_IMPLEMENTATION)
#ifdef _WIN32
// on Windows, the iostream-based implementation of atof is extremely slow,
-// and we do have a locale independent version of sscanf. Use this version.
-#define ENABLE_CSTDIO_BASED_ATOF_IMPLEMENTATION
+// and we do have a locale independent version of sprintf, called _snprintf_s_l.
+// Use this version.
+#define ENABLE_CSTDIO_BASED_FTOA_IMPLEMENTATION
#else
// on other platforms, we assume that the iobased-implementation, being the
// cleanest one, is appropriate. This is known to be the case for gcc and clang with glibc.
return ::vsnprintf(str, size, format, ap);
#endif /* _MSC_VER < 1900 */
#else /* _MSC_VER */
-#ifdef HAVE_VSNPRINTF
return ::vsnprintf(str, size, format, ap);
-#else /* HAVE_VSNPRINTF */
-#ifdef DCMTK_ENABLE_UNSAFE_VSNPRINTF
- // This implementation internally uses vsprintf (which is inherently unsafe).
- // It allocates a buffer that is 1 kByte larger than "size",
- // formats the string into that buffer, and then uses strlcpy() to
- // copy the formatted string into the output buffer, truncating if necessary.
- // This will work in most cases, since few snprintf calls should overrun
- // the provided buffer by more than 1K, but it can be easily abused by
- // a malicious attacker to cause a buffer overrun.
- //
- // Therefore, this implementation should only be used as a "last resort"
- // and we strongly advise against using it in production code.
- // The macro "DCMTK_ENABLE_UNSAFE_VSNPRINTF" must explicitly be defined
- // by the used to enable this implementation.
- int count = -1;
- if (size != 0)
- {
- char *buf = new char[size+1024];
- count = ::vsprintf(buf, format, ap);
- OFStandard::strlcpy(str, buf, size);
- delete[] buf;
- }
- return count;
-#warning Using unsafe implementation of vsnprintf(3)
-#else /* DCMTK_ENABLE_UNSAFE_VSNPRINTF */
- return -1;
-#error vsnprintf(3) not found. Use different compiler or compile with DCMTK_ENABLE_UNSAFE_VSNPRINTF (unsafe!)
-#endif /* DCMTK_ENABLE_UNSAFE_VSNPRINTF */
-#endif /* HAVE_VSNPRINTF */
#endif /* _MSC_VER */
}
/* check for valid path name (avoid NULL or empty string) */
if (!pathName.isEmpty())
{
-#ifdef HAVE_ACCESS
/* check existence with "access()" */
#if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
/* check whether to use the wide-char version of the API function */
else
#endif
result = (access(pathName.getCharPointer(), F_OK) == 0);
-#else /* HAVE_ACCESS */
-#ifdef HAVE_WINDOWS_H
- /* get file attributes */
- DWORD fileAttr;
-#if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
- /* check whether to use the wide-char version of the API function */
- if (pathName.usesWideChars())
- fileAttr = GetFileAttributesW(pathName.getWideCharPointer());
- else
-#endif
- fileAttr = GetFileAttributes(pathName.getCharPointer());
- result = (fileAttr != 0xffffffff);
-#else /* HAVE_WINDOWS_H */
-#ifdef HAVE_SYS_STAT_H
- /* check existence with "stat()" */
- struct stat stat_buf;
- result = (stat(pathName.getCharPointer(), &stat_buf) == 0);
-#else
- /* try to open the given "file" (or directory) in read-only mode */
- OFFile file;
- result = file.fopen(pathName, "r");
- file.fclose();
-#endif /* HAVE_SYS_STAT_H */
-#endif /* HAVE_WINDOWS_H */
-#endif /* HAVE_ACCESS */
}
return result;
}
/* check for valid path name (avoid NULL or empty string) */
if (!pathName.isEmpty())
{
-#ifdef HAVE_ACCESS
/* check whether the path is readable using "access()" */
#if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
/* check whether to use the wide-char version of the API function */
else
#endif
result = (access(pathName.getCharPointer(), R_OK) == 0);
-#else /* HAVE_ACCESS */
- /* try to open the given "file" (or directory) in read-only mode */
- OFFile file;
- result = file.fopen(pathName, "r");
-#endif /* HAVE_ACCESS */
}
return result;
}
/* check for valid path name (avoid NULL or empty string) */
if (!pathName.isEmpty())
{
-#ifdef HAVE_ACCESS
/* check whether the path is writable using "access()" */
#if defined(WIDE_CHAR_FILE_IO_FUNCTIONS) && defined(_WIN32)
/* check whether to use the wide-char version of the API function */
else
#endif
result = (access(pathName.getCharPointer(), W_OK) == 0);
-#else /* HAVE_ACCESS */
- /* try to open the given "file" (or directory) in write mode */
- OFFile file;
- result = file.fopen(pathName, "w");
-#endif /* HAVE_ACCESS */
}
return result;
}
return OFnumeric_limits<double>::quiet_NaN();
}
+ // handle negative NaN as a special case, since iostream does not
+ if ((ss.length() >= 4) && (ss[0] == '-') && (ss[1] == 'n' || ss[1] == 'N') && (ss[2] == 'a' || ss[2] == 'A') && (ss[3] == 'n' || ss[3] == 'N'))
+ {
+ if (success) *success = OFTrue;
+ return OFnumeric_limits<double>::quiet_NaN();
+ }
+
// handle positive infinity as a special case, since iostream does not
if ((ss.length() >= 3) && (ss[0] == 'i' || ss[0] == 'I') && (ss[1] == 'n' || ss[1] == 'N') && (ss[2] == 'f' || ss[2] == 'F'))
{
#else /* ENABLE_IOSTREAM_BASED_ATOF_IMPLEMENTATION */
+// This is the implementation in use when ENABLE_CSTDIO_BASED_ATOF_IMPLEMENTATION
+// is defined.
+
#ifdef _WIN32
// Windows has a sscanf version where we can explicitly pass a locale
#else /* ENABLE_IOSTREAM_BASED_FTOA_IMPLEMENTATION */
+// This is the implementation in use when ENABLE_CSTDIO_BASED_FTOA_IMPLEMENTATION
+// is defined.
+
static void ftoa_convert(
char *dst,
size_t siz,
if (!success || d != val)
{
// really need precision 17 (DBL_DECIMAL_DIG)
- ftoa_convert(dst, siz, val, flags, width, prec);
+ ftoa_convert(dst, siz, val, flags, width, 17);
}
}
else
{
#ifdef _WIN32
return _getpid();
-#elif defined(HAVE_GETPID)
- return getpid();
#else
- return 0; // Workaround for MAC
+ return getpid();
#endif
}
/*
*
- * Copyright (C) 2024, OFFIS e.V.
+ * Copyright (C) 2024-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
return OFString();
}
+#elif defined(__APPLE__)
+
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+
#else /* _WIN32 */
extern char** environ; // required to exist by the Single Unix Specification
return EXITCODE_ILLEGAL_PARAMS;
}
+ long len = 43 - OFstatic_cast(long, strlen(stubName)) - OFstatic_cast(long, strlen(appName));
+ if (len < 0) len = 0;
+
#ifdef DCMTK_USE_OFLOG_LOGGER_IN_STUB
OFString logger_name = "dcmtk.apps.";
logger_name += stubName;
OFLogger logger = OFLog::getLogger(logger_name.c_str());
-#endif
-#ifdef DCMTK_USE_OFLOG_LOGGER_IN_STUB
- OFLOG_WARN(logger, stubName << " is deprecated, use " << appName << " instead");
+ OFString output =
+ "##########################################################################\n"
+ "# #\n#";
+ output.append(len/2, ' ');
+ output.append(stubName);
+ output.append(" is deprecated, use ");
+ output.append(appName);
+ output.append(" instead!");
+ output.append(len - (len/2), ' ');
+ output.append("#\n"
+ "# #\n"
+ "##########################################################################\n");
+ OFLOG_WARN(logger, output);
#else
- fprintf(stderr, "W: %s is deprecated, use %s instead\n", stubName, appName);
+ OFString output =
+ "W: ##########################################################################\n"
+ "W: # #\nW: #";
+ output.append(len/2, ' ');
+ output.append(stubName);
+ output.append(" is deprecated, use ");
+ output.append(appName);
+ output.append(" instead!");
+ output.append(len - (len/2), ' ');
+ output.append("#\n"
+ "W: # #\n"
+ "W: ##########################################################################\n\n");
+
+ fprintf(stderr, "%s", output.c_str());
#endif
// get real path in which the stub executable is located
/*
*
- * Copyright (C) 2011-2023, OFFIS e.V.
+ * Copyright (C) 2011-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were slightly modified by
}
static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); }
static inline int xstrlen(XMLCSTR c) { return OFstatic_cast(int, strlen(c)); }
- #ifdef __BORLANDC__
+ #ifdef HAVE_CLASSIC_BORLAND_COMPILER
static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strnicmp(c1,c2,l);}
static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return stricmp(c1,c2); }
#else
../include/dcmtk/ofstd/ofstring.h ../include/dcmtk/ofstd/oftypes.h \
../include/dcmtk/ofstd/ofdefine.h ../include/dcmtk/ofstd/ofcast.h \
../include/dcmtk/ofstd/ofexport.h ../include/dcmtk/ofstd/ofstdinc.h \
- ../include/dcmtk/ofstd/ofstream.h ../include/dcmtk/ofstd/oftest.h \
- ../include/dcmtk/ofstd/ofconapp.h ../include/dcmtk/ofstd/ofcmdln.h \
- ../include/dcmtk/ofstd/ofexbl.h ../include/dcmtk/ofstd/oftraits.h \
- ../include/dcmtk/ofstd/oflist.h ../include/dcmtk/ofstd/ofconsol.h \
- ../include/dcmtk/ofstd/ofthread.h ../include/dcmtk/ofstd/offile.h \
- ../include/dcmtk/ofstd/ofstd.h ../include/dcmtk/ofstd/ofcond.h \
- ../include/dcmtk/ofstd/ofdiag.h ../include/dcmtk/ofstd/diag/push.def \
+ ../include/dcmtk/ofstd/ofstream.h ../include/dcmtk/ofstd/ofstrhlp.h \
+ ../include/dcmtk/ofstd/oftest.h ../include/dcmtk/ofstd/ofconapp.h \
+ ../include/dcmtk/ofstd/ofcmdln.h ../include/dcmtk/ofstd/ofexbl.h \
+ ../include/dcmtk/ofstd/oftraits.h ../include/dcmtk/ofstd/oflist.h \
+ ../include/dcmtk/ofstd/ofconsol.h ../include/dcmtk/ofstd/ofthread.h \
+ ../include/dcmtk/ofstd/offile.h ../include/dcmtk/ofstd/ofstd.h \
+ ../include/dcmtk/ofstd/ofcond.h ../include/dcmtk/ofstd/ofdiag.h \
+ ../include/dcmtk/ofstd/diag/push.def \
../include/dcmtk/ofstd/diag/useafree.def \
../include/dcmtk/ofstd/diag/pop.def ../include/dcmtk/ofstd/oflimits.h \
../include/dcmtk/ofstd/oferror.h ../include/dcmtk/ofstd/ofexit.h
/*
*
- * Copyright (C) 2011-2024, OFFIS e.V.
+ * Copyright (C) 2011-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
OFTEST_REGISTER(ofstd_OFString_compare);
OFTEST_REGISTER(ofstd_OFString_concatenate);
OFTEST_REGISTER(ofstd_OFString_constructor);
+OFTEST_REGISTER(ofstd_OFString_conversion);
OFTEST_REGISTER(ofstd_OFString_copy);
OFTEST_REGISTER(ofstd_OFString_identity_1);
OFTEST_REGISTER(ofstd_OFString_identity_2);
/*
*
- * Copyright (C) 1997-2019, OFFIS e.V.
+ * Copyright (C) 1997-2025, OFFIS e.V.
* All rights reserved. See COPYRIGHT file for details.
*
* This software and supporting documentation were developed by
#include "dcmtk/config/osconfig.h" /* include OS specific configuration first */
#include "dcmtk/ofstd/ofstring.h"
+#include "dcmtk/ofstd/ofstrhlp.h"
#define OFTEST_OFSTD_ONLY
#include "dcmtk/ofstd/oftest.h"
{
identitytest(X+Y+N+X+Y+N, "A string that will be used in identitytest but is otherwise just another useless string.");
}
+
+OFTEST(ofstd_OFString_conversion)
+{
+ // convert an OFString to std::string
+ OFString a("ABC");
+ STD_NAMESPACE string b = OFString_to_std_string(a);
+ OFCHECK_EQUAL(b.length(), 3);
+ OFCHECK_EQUAL(b.at(0), 'A');
+ OFCHECK_EQUAL(b.at(1), 'B');
+ OFCHECK_EQUAL(b.at(2), 'C');
+
+ // convert an OFString containing a null byte to std::string
+ a.at(1)= '\0';
+ STD_NAMESPACE string cc = OFString_to_std_string(a);
+ OFCHECK_EQUAL(cc.length(), 3);
+ OFCHECK_EQUAL(cc.at(0), 'A');
+ OFCHECK_EQUAL(cc.at(1), '\0');
+ OFCHECK_EQUAL(cc.at(2), 'C');
+
+ // convert a std::string to OFString
+ OFString d = std_string_to_OFString(b);
+ OFCHECK_EQUAL(d.length(), 3);
+ OFCHECK_EQUAL(d.at(0), 'A');
+ OFCHECK_EQUAL(d.at(1), 'B');
+ OFCHECK_EQUAL(d.at(2), 'C');
+
+ // convert a std::string containing a null byte to OFString
+ OFString e = std_string_to_OFString(cc);
+ OFCHECK_EQUAL(e.length(), 3);
+ OFCHECK_EQUAL(e.at(0), 'A');
+ OFCHECK_EQUAL(e.at(1), '\0');
+ OFCHECK_EQUAL(e.at(2), 'C');
+}